import { pool } from "../db/pool.js";
import { ApiError } from "../utils/ApiError.js";
import { logAudit } from "../utils/auditLog.js";
import {
  exportFiscalAnnualSummaryExcel,
  exportFiscalAnnualSummaryPdf,
  generateFiscalDeadlines,
  getFiscalAnnualSummaryData,
  getFiscalCalendarData,
} from "../utils/fiscalDeadlines.js";

const getCompanyId = (req, source = req.query) => {
  const companyId = Number(source.company_id || source.companyId || req.user?.companyId || 0);

  if (!companyId) {
    throw new ApiError(400, "company_id is required.");
  }

  return companyId;
};

const parseYear = (value) => {
  const year = Number(value || 0);
  return Number.isFinite(year) && year > 0 ? year : new Date().getUTCFullYear();
};

const fetchFiscalYear = async (db, companyId, fiscalYearId) => {
  const { rows } = await db.query(
    `
      SELECT
        id,
        label,
        TO_CHAR(start_date, 'YYYY-MM-DD') AS start_date,
        TO_CHAR(end_date, 'YYYY-MM-DD') AS end_date,
        is_current
      FROM fiscal_years
      WHERE company_id = $1
        AND id = $2
      LIMIT 1
    `,
    [companyId, fiscalYearId],
  );

  if (!rows[0]) {
    throw new ApiError(404, "Exercice fiscal introuvable.");
  }

  return {
    id: Number(rows[0].id),
    label: rows[0].label,
    start_date: rows[0].start_date,
    end_date: rows[0].end_date,
    is_current: rows[0].is_current,
  };
};

export const fiscalCalendarController = {
  getCalendar: async (req, res) => {
    const companyId = getCompanyId(req);
    const annee = parseYear(req.query.annee);
    const client = await pool.connect();

    try {
      await client.query("BEGIN");

      const data = await getFiscalCalendarData(client, {
        companyId,
        annee,
        userId: req.user?.sub || req.user?.id || null,
        io: req.app.get("io"),
      });

      await client.query("COMMIT");

      res.json({
        company_id: companyId,
        annee,
        items: data.items,
        summary_cards: data.summary_cards,
        urgent_count: data.urgent_count,
        meta: {
          available_years: data.available_years,
        },
      });
    } catch (error) {
      await client.query("ROLLBACK").catch(() => {});
      throw error;
    } finally {
      client.release();
    }
  },

  generateDeadlines: async (req, res) => {
    const companyId = getCompanyId(req);
    const fiscalYearId = Number(req.query.fiscal_year_id || req.body?.fiscal_year_id || 0);

    if (!fiscalYearId) {
      throw new ApiError(400, "fiscal_year_id is required.");
    }

    const client = await pool.connect();

    try {
      await client.query("BEGIN");

      const fiscalYear = await fetchFiscalYear(client, companyId, fiscalYearId);
      const rows = await generateFiscalDeadlines(client, {
        companyId,
        fiscalYear,
        userId: req.user?.sub || req.user?.id || null,
        io: req.app.get("io"),
      });

      await logAudit(client, {
        companyId,
        userId: req.user?.sub || req.user?.id || null,
        action: "fiscal.calendar.generate_deadlines",
        entityType: "fiscal_deadlines",
        entityId: fiscalYear.id,
        newData: {
          fiscal_year_id: fiscalYear.id,
          generated_count: rows.length,
        },
        ipAddress: req.ip,
      });

      await client.query("COMMIT");

      res.json({
        message: "Echeances fiscales regenerees.",
        company_id: companyId,
        fiscal_year_id: fiscalYear.id,
        generated_count: rows.length,
      });
    } catch (error) {
      await client.query("ROLLBACK").catch(() => {});
      throw error;
    } finally {
      client.release();
    }
  },

  getAnnualSummary: async (req, res) => {
    const companyId = getCompanyId(req);
    const annee = parseYear(req.query.annee);
    const client = await pool.connect();

    try {
      await client.query("BEGIN");

      const data = await getFiscalAnnualSummaryData(client, {
        companyId,
        annee,
        userId: req.user?.sub || req.user?.id || null,
        io: req.app.get("io"),
      });

      await client.query("COMMIT");

      res.json({
        company_id: companyId,
        annee: data.annee,
        items: data.items,
        totals: data.totals,
        meta: {
          available_years: data.available_years,
        },
      });
    } catch (error) {
      await client.query("ROLLBACK").catch(() => {});
      throw error;
    } finally {
      client.release();
    }
  },

  exportAnnualSummaryPdf: async (req, res) => {
    const companyId = getCompanyId(req);
    const annee = parseYear(req.query.annee);
    const client = await pool.connect();

    try {
      await client.query("BEGIN");

      const data = await getFiscalAnnualSummaryData(client, {
        companyId,
        annee,
        userId: req.user?.sub || req.user?.id || null,
        io: req.app.get("io"),
      });

      await client.query("COMMIT");

      const buffer = await exportFiscalAnnualSummaryPdf({
        company: data.company,
        annee: data.annee,
        items: data.items,
        totals: data.totals,
        generatedBy: req.user?.fullName || req.user?.email || "Systeme",
      });

      res.setHeader("Content-Type", "application/pdf");
      res.setHeader(
        "Content-Disposition",
        `inline; filename="recapitulatif-fiscal-annuel-${data.annee}.pdf"`,
      );
      res.send(Buffer.from(buffer));
    } catch (error) {
      await client.query("ROLLBACK").catch(() => {});
      throw error;
    } finally {
      client.release();
    }
  },

  exportAnnualSummaryExcel: async (req, res) => {
    const companyId = getCompanyId(req);
    const annee = parseYear(req.query.annee);
    const client = await pool.connect();

    try {
      await client.query("BEGIN");

      const data = await getFiscalAnnualSummaryData(client, {
        companyId,
        annee,
        userId: req.user?.sub || req.user?.id || null,
        io: req.app.get("io"),
      });

      await client.query("COMMIT");

      const buffer = await exportFiscalAnnualSummaryExcel({
        company: data.company,
        annee: data.annee,
        items: data.items,
        totals: data.totals,
        generatedBy: req.user?.fullName || req.user?.email || "Systeme",
      });

      res.setHeader(
        "Content-Type",
        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
      );
      res.setHeader(
        "Content-Disposition",
        `attachment; filename="recapitulatif-fiscal-annuel-${data.annee}.xlsx"`,
      );
      res.send(Buffer.from(buffer));
    } catch (error) {
      await client.query("ROLLBACK").catch(() => {});
      throw error;
    } finally {
      client.release();
    }
  },
};
