import { TRPCError } from "@trpc/server";
import { endOfMonth, format, getUnixTime } from "date-fns";
import { it } from "date-fns/locale";
import Papa from "papaparse";
import { z } from "zod/v4";
import stripe from "~/lib/stripe";
import { adminProcedure, createTRPCRouter } from "~/server/api/trpc";
import { TypstGenerate } from "~/server/services/typst.service";
export const stripeReportsRouter = createTRPCRouter({
	listReports: adminProcedure.query(async () => {
		try {
			const reports = await stripe.reporting.reportRuns.list({ limit: 20 });
			return reports.data;
		} catch (error) {
			throw new TRPCError({
				code: "INTERNAL_SERVER_ERROR",
				message: `Error listing reports: ${(error as Error).message}`,
				cause: error,
			});
		}
	}),

	setupEstrattoConto: adminProcedure
		.input(
			z.object({
				start: z.date(),
			}),
		)
		.mutation(async ({ input }) => {
			const start = getUnixTime(input.start);
			const end = getUnixTime(endOfMonth(input.start));

			try {
				await stripe.reporting.reportRuns.create({
					report_type: "balance_change_from_activity.itemized.1",
					parameters: {
						interval_start: start,
						interval_end: end,
						columns: [
							"balance_transaction_id",
							"created_utc",
							"customer_email",
							"customer_name",
							"description",
							"fee",
							"gross",
							"net",
							"payment_method_type",
						],
					},
				});
				await stripe.reporting.reportRuns.create({
					report_type: "balance.summary.1",
					parameters: {
						interval_start: start,
						interval_end: end,
					},
				});
			} catch (error) {
				throw new TRPCError({
					code: "INTERNAL_SERVER_ERROR",
					message: `Error generating estratto conto: ${(error as Error).message}`,
					cause: error,
				});
			}
		}),
	generateEstrattoConto: adminProcedure
		.input(
			z.object({
				movimentiUrl: z.string(),
				saldoUrl: z.string(),
			}),
		)
		.mutation(async ({ input }) => {
			try {
				const movimentiCSV = await fetch(input.movimentiUrl, {
					headers: {
						Authorization: `Bearer ${process.env.STRIPE_SECRET_KEY}`,
					},
				}).then((res) => res.text());
				const saldoCSV = await fetch(input.saldoUrl, {
					headers: {
						Authorization: `Bearer ${process.env.STRIPE_SECRET_KEY}`,
					},
				}).then((res) => res.text());

				const { data: movimentiData, errors: movimentiErrors } = Papa.parse(
					movimentiCSV,
					{
						header: true, // Uses first row as keys
						skipEmptyLines: true,
						dynamicTyping: true, // Handles numbers/booleans
					},
				);
				if (movimentiErrors.length > 0) {
					return {
						success: false,
						message: movimentiErrors.map((e) => e.message).join(", "),
					};
				}

				const { data: saldoData, errors: saldoErrors } = Papa.parse(saldoCSV, {
					header: true, // Uses first row as keys
					skipEmptyLines: true,
					dynamicTyping: true, // Handles numbers/booleans
				});
				if (saldoErrors.length > 0) {
					return {
						success: false,
						message: saldoErrors.map((e) => e.message).join(", "),
					};
				}

				const movimenti = z.array(movimentiSchema).safeParse(movimentiData);
				const saldi = z.array(saldoSchema).safeParse(saldoData);

				if (!movimenti.success) {
					console.error("Movimenti validation errors:", movimenti.error);
					return {
						success: false,
						message: `Movimenti CSV validation error: ${movimenti.error.message}`,
					};
				}
				if (!saldi.success) {
					console.error("Saldo validation errors:", saldi.error);
					return {
						success: false,
						message: `Saldo CSV validation error: ${saldi.error.message}`,
					};
				}
				const startingBalance = saldi.data.find(
					(s) => s.category === "starting_balance",
				);
				const endingBalance = saldi.data.find(
					(s) => s.category === "ending_balance",
				);
				if (!startingBalance || !endingBalance) {
					return {
						success: false,
						message: "Missing starting or ending balance in saldo report",
					};
				}

				const data: EstrattoContoData = {
					interval: `${format(new Date(startingBalance.description.replace(/[^\d-]/gm, "")), "dd/MM/yyyy", { locale: it }) || "N/A"} - ${format(new Date(endingBalance.description.replace(/[^\d-]/gm, "")), "dd/MM/yyyy", { locale: it }) || "N/A"}`,
					emissione: format(new Date(), "dd/MM/yyyy", { locale: it }),
					starting_balance: startingBalance?.net_amount * 100 || 0,
					ending_balance: endingBalance?.net_amount * 100 || 0,
					activity_gross:
						(saldi.data.find((s) => s.category === "activity_gross")
							?.net_amount || 0) * 100,
					activity_fee:
						(saldi.data.find((s) => s.category === "activity_fee")
							?.net_amount || 0) * -100,
					payouts:
						saldi.data.find((s) => s.category === "payouts")?.net_amount || 0,
					movimenti: movimenti.data.map((m) => ({
						date: format(new Date(m.created_utc), "dd/MM/yyyy", {
							locale: it,
						}),
						description: m.description || "",
						gross: m.gross * 100,
						net: m.net * 100,
						fees: m.fee * 100,
						name: m.customer_name || "",
						email: m.customer_email || "",
					})),
				};
				const pdf = await TypstGenerate({ templateId: "estratto.typ", data });

				return {
					success: true,
					data: {
						pdf: pdf.toString("base64"),
						title: `Estratto Conto ${data.interval}.pdf`,
					},
				};
			} catch (error) {
				throw new TRPCError({
					code: "INTERNAL_SERVER_ERROR",
					message: `Error generating estratto conto: ${(error as Error).message}`,
					cause: error,
				});
			}
		}),
});
//stripe reporting report_runs create --report-type "balance.summary.1" --parameters.interval-start 1772323200 --parameters.interval-end 1775001599

const movimentiSchema = z.object({
	balance_transaction_id: z.string(),
	created_utc: z.string(),
	customer_email: z.email().nullable(),
	customer_name: z.string().nullable(),
	description: z.string().nullable(),
	fee: z.number(),
	gross: z.number(),
	net: z.number(),
	payment_method_type: z.string().nullable(),
});
const saldoSchema = z.object({
	category: z.string(),
	currency: z.string().nullable(),
	description: z.string(),
	net_amount: z.number(),
});

export type EstrattoContoData = {
	interval: string;
	emissione: string;
	starting_balance: number;
	ending_balance: number;
	activity_gross: number; // Entrate lorde
	activity_fee: number; // Commissioni
	payouts: number; // Prelievi verso conto bancario
	movimenti: {
		date: string;
		description: string;
		gross: number;
		net: number;
		fees: number;
		name: string;
		email: string;
	}[];
};
