import type pg from 'pg';
import type { PosStoreRepository } from '../domain/ports.js';
import type { PosStore, ListStoresOptions } from '../domain/store.js';

interface StoreRow {
  id: string;
  name: string;
  slug: string;
  address: string | null;
  tax_id: string | null;
  contact_email: string | null;
  contact_phone: string | null;
  receipt_header: string | null;
  receipt_footer: string | null;
  settings: Record<string, unknown>;
  active: boolean;
  created_at: Date;
  updated_at: Date;
}

function toStore(row: StoreRow): PosStore {
  return {
    id: row.id,
    name: row.name,
    slug: row.slug,
    address: row.address,
    taxId: row.tax_id,
    contactEmail: row.contact_email,
    contactPhone: row.contact_phone,
    receiptHeader: row.receipt_header,
    receiptFooter: row.receipt_footer,
    settings: row.settings,
    active: row.active,
    createdAt: row.created_at,
    updatedAt: row.updated_at,
  };
}

export class PgStoreRepository implements PosStoreRepository {
  constructor(private readonly pool: pg.Pool) {}

  async findById(id: string): Promise<PosStore | undefined> {
    const result = await this.pool.query<StoreRow>(
      'SELECT * FROM pos_stores WHERE id = $1',
      [id],
    );
    return result.rows[0] ? toStore(result.rows[0]) : undefined;
  }

  async list(options: ListStoresOptions = {}): Promise<{ stores: PosStore[]; total: number }> {
    const { active = true, limit = 50, offset = 0 } = options;
    const where = active !== undefined ? 'WHERE active = $1' : '';
    const countParams: number[] = active !== undefined ? [active ? 1 : 0] : [];
    const listParams: number[] = [...countParams, limit, offset];

    const [countResult, listResult] = await Promise.all([
      this.pool.query<{ count: string }>(
        `SELECT COUNT(*) as count FROM pos_stores ${where}`,
        countParams,
      ),
      this.pool.query<StoreRow>(
        `SELECT * FROM pos_stores ${where} ORDER BY name LIMIT $${listParams.length - 1} OFFSET $${listParams.length}`,
        listParams,
      ),
    ]);

    return {
      stores: listResult.rows.map(toStore),
      total: parseInt(countResult.rows[0]?.count ?? '0', 10),
    };
  }
}
