const Country = require('../../models/Country');
const { VatRate, VatRateHistory, VAT_FIELDS } = require('../../models/Tax');

class TaxRepository {
  constructor(uow) {
    this.uow = uow;
    this.conn = uow.getConnection();
  }

  async upsertCountries(countries, actorUserId) {
    let created = 0;
    let updated = 0;
    for (const c of countries) {
      const [res] = await this.conn.query(
        `INSERT INTO countries (country_code, country_name, created_by, updated_by)
         VALUES (?, ?, ?, ?)
         ON DUPLICATE KEY UPDATE country_name=VALUES(country_name), updated_by=VALUES(updated_by), updated_at=CURRENT_TIMESTAMP`,
        [c.code, c.name, actorUserId || null, actorUserId || null]
      );
      if (res.affectedRows === 1) created += 1;
      if (res.affectedRows === 2) updated += 1;
    }
    return { created, updated };
  }

  async getCountriesByCodes(codes) {
    if (!codes.length) return {};
    const [rows] = await this.conn.query(
      `SELECT * FROM countries WHERE country_code IN (${codes.map(() => '?').join(',')})`,
      codes
    );
    const map = {};
    rows.forEach((r) => { map[r.country_code] = new Country(r); });
    return map;
  }

  async getCountryByCode(code) {
    const [rows] = await this.conn.query(`SELECT * FROM countries WHERE country_code = ? LIMIT 1`, [code]);
    return rows[0] ? new Country(rows[0]) : null;
  }

  async getAllCurrentVatRates() {
    const [rows] = await this.conn.query(
      `SELECT c.*, vr.id AS vat_id, vr.standard_rate, vr.reduced_rate, vr.super_reduced_rate, vr.parking_rate, vr.effective_from
       FROM countries c
       LEFT JOIN vat_rates vr ON vr.country_id = c.id AND vr.effective_to IS NULL
       ORDER BY c.country_name ASC`
    );
    return rows;
  }

  async getVatHistory(countryId) {
    const [rows] = await this.conn.query(
      `SELECT * FROM vat_rate_history WHERE country_id = ? ORDER BY effective_from DESC`,
      [countryId]
    );
    return rows.map((r) => new VatRateHistory(r));
  }

  async setCurrentVatRate(countryId, rates, actorUserId) {
    const [currentRows] = await this.conn.query(
      `SELECT * FROM vat_rates WHERE country_id = ? AND effective_to IS NULL LIMIT 1`,
      [countryId]
    );
    const now = new Date();
    const current = currentRows[0] ? new VatRate(currentRows[0]) : null;

    const areEqual =
      current &&
      VAT_FIELDS.every((k) => {
        const a = current[k] == null ? null : Number(current[k]);
        const b = rates[k] == null ? null : Number(rates[k]);
        return (a === null && b === null) || a === b;
      });

    if (areEqual) return { changed: false, skipped: true };

    if (current) {
      await this.conn.query(
        `INSERT INTO vat_rate_history (country_id, standard_rate, reduced_rate, super_reduced_rate, parking_rate, effective_from, effective_to, created_by, updated_by)
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
        [
          countryId,
          current.standard_rate,
          current.reduced_rate,
          current.super_reduced_rate,
          current.parking_rate,
          current.effective_from,
          now,
          actorUserId || current.created_by || null,
          actorUserId || current.updated_by || null
        ]
      );
      await this.conn.query(
        `UPDATE vat_rates SET effective_to = ?, updated_by = ? WHERE id = ?`,
        [now, actorUserId || null, current.id]
      );
    }

    await this.conn.query(
      `INSERT INTO vat_rates (country_id, standard_rate, reduced_rate, super_reduced_rate, parking_rate, effective_from, effective_to, created_by, updated_by)
       VALUES (?, ?, ?, ?, ?, ?, NULL, ?, ?)`,
      [
        countryId,
        rates.standard_rate,
        rates.reduced_rate,
        rates.super_reduced_rate,
        rates.parking_rate,
        now,
        actorUserId || null,
        actorUserId || null
      ]
    );

    return { changed: true, skipped: false };
  }

  async bulkImportVatRates(entries, actorUserId) {
    let ratesUpdated = 0;
    let ratesSkipped = 0;
    for (const entry of entries) {
      const res = await this.setCurrentVatRate(entry.country_id, entry.rates, actorUserId);
      if (res.changed) ratesUpdated += 1;
      if (res.skipped) ratesSkipped += 1;
    }
    return { ratesUpdated, ratesSkipped };
  }
}

module.exports = TaxRepository;
