import { NextResponse } from "next/server";
import { createClient } from "@/lib/supabase-server";
import { canCompany, getCompanyContext } from "@/lib/company-context";

function parseMonthRange(value: string) {
  if (!/^\d{4}-\d{2}$/.test(value)) return null;
  const [yearRaw, monthRaw] = value.split("-");
  const year = Number(yearRaw);
  const month = Number(monthRaw);
  if (!Number.isInteger(year) || !Number.isInteger(month)) return null;
  if (month < 1 || month > 12) return null;
  const start = new Date(Date.UTC(year, month - 1, 1, 0, 0, 0));
  const end = new Date(Date.UTC(year, month, 1, 0, 0, 0));
  return {
    start: start.toISOString().slice(0, 10),
    end: end.toISOString().slice(0, 10),
  };
}

function getPreviousMonth(value: string) {
  const [yearRaw, monthRaw] = value.split("-");
  const year = Number(yearRaw);
  const month = Number(monthRaw);
  const date = new Date(Date.UTC(year, month - 1, 1, 0, 0, 0));
  date.setUTCMonth(date.getUTCMonth() - 1);
  const prevYear = date.getUTCFullYear();
  const prevMonth = String(date.getUTCMonth() + 1).padStart(2, "0");
  return `${prevYear}-${prevMonth}`;
}

type DreTotals = {
  revenue: number;
  expenses_total: number;
  adjustments: number;
  net_result: number;
  margin_percent: number;
};

type DeltaMetric = {
  value: number;
  percent: number | null;
  trend: "up" | "down" | "stable";
};

function calcMargin(revenue: number, netResult: number) {
  if (revenue === 0) return 0;
  return (netResult / revenue) * 100;
}

function calcDelta(current: number, previous: number): DeltaMetric {
  const value = current - previous;
  const percent = previous === 0 ? null : (value / previous) * 100;
  let trend: DeltaMetric["trend"] = "stable";
  if (current > previous) trend = "up";
  if (current < previous) trend = "down";
  return { value, percent, trend };
}

export async function GET(req: Request) {
  const supabase = await createClient();
  const {
    data: { user },
    error: userError,
  } = await supabase.auth.getUser();

  if (userError || !user) {
    return NextResponse.json({ error: "Não autenticado." }, { status: 401 });
  }

  const ctx = await getCompanyContext(supabase, user);
  if (!canCompany(ctx, user.id, "financial.dre.read")) {
    return NextResponse.json({ error: "Sem permissão." }, { status: 403 });
  }

  const url = new URL(req.url);
  const month = url.searchParams.get("month")?.trim() ?? "";
  const bankAccountId = url.searchParams.get("bank_account_id")?.trim() ?? "";
  const monthRange = month ? parseMonthRange(month) : null;

  if (!monthRange) {
    return NextResponse.json({ error: "Parâmetro 'month' inválido." }, { status: 400 });
  }

  const previousMonth = getPreviousMonth(month);
  const previousRange = parseMonthRange(previousMonth);

  if (!previousRange) {
    return NextResponse.json({ error: "Parâmetro 'month' inválido." }, { status: 400 });
  }

  const buildTotals = async (range: { start: string; end: string }): Promise<DreTotals> => {
    let query = supabase
      .from("cash_flow")
      .select("origin,type,total:amount.sum()")
      .eq("company_id", ctx.companyId)
      .gte("date", range.start)
      .lt("date", range.end);

    if (bankAccountId) {
      query = query.eq("bank_account_id", bankAccountId);
    }

    const { data, error } = await query;
    if (error) {
      throw error;
    }

    const rows = (data ?? []) as Array<{ origin: string | null; type: string | null; total: number | null }>;

    const sumBy = (origin: string, type: "IN" | "OUT") =>
      rows
        .filter((row) => row.origin === origin && row.type === type)
        .reduce((acc, row) => acc + Number(row.total ?? 0), 0);

    const revenue = sumBy("PEDIDO", "IN") + sumBy("RECEBER", "IN");
    const expensesTotal = sumBy("PAGAR", "OUT");
    const adjustmentsIn = sumBy("AJUSTE", "IN");
    const adjustmentsOut = sumBy("AJUSTE", "OUT");
    const adjustments = adjustmentsIn - adjustmentsOut;
    const netResult = revenue - expensesTotal + adjustments;
    const marginPercent = calcMargin(revenue, netResult);

    return {
      revenue,
      expenses_total: expensesTotal,
      adjustments,
      net_result: netResult,
      margin_percent: marginPercent,
    };
  };

  try {
    const [current, previous] = await Promise.all([
      buildTotals(monthRange),
      buildTotals(previousRange),
    ]);

    const delta = {
      revenue: calcDelta(current.revenue, previous.revenue),
      expenses: calcDelta(current.expenses_total, previous.expenses_total),
      net_result: calcDelta(current.net_result, previous.net_result),
    };

    return NextResponse.json({
      current,
      previous,
      delta,
    });
  } catch {
    return NextResponse.json({ error: "Falha ao carregar análise do DRE." }, { status: 500 });
  }
}
