import Link from "next/link";
import { AppShell } from "@/components/AppShell";
import { ChartPanel, DistributionPieChart, MultiBarChart, MultiLineChart, SimpleLineChart, SingleBarChart } from "@/components/Charts";
import { EmptyState } from "@/components/EmptyState";
import { PageHeader } from "@/components/PageHeader";
import { StatCard } from "@/components/StatCard";
import { SummaryCard } from "@/components/SummaryCard";
import { expenseByCategory, expenseByDay, expenseByMonth, expenseByWeek, initialInvestmentByPhase, operatingExpensesByMonth, partnerBalanceChart, profitLossByMonth, rentByMonth } from "@/lib/chartData";
import { filterExpenses, parseExpenseFilters } from "@/lib/expenseFilters";
import { currency } from "@/lib/format";
import { buildProjectMetrics } from "@/lib/metrics";
import { getSelectedProject } from "@/lib/projects";
import { prisma } from "@/lib/prisma";
import { billTimingMessage, effectiveBillStatus, recurringBillStatusLabels, startOfDay, statusTone } from "@/lib/recurringBills";

export default async function DashboardPage({
  searchParams
}: {
  searchParams?: Promise<Record<string, string | string[] | undefined>>;
}) {
  const params = (await searchParams) ?? {};
  const selected = typeof params.projectId === "string" ? params.projectId : undefined;
  const { user, projects, project, permissions, projectRole } = await getSelectedProject(selected, "dashboard.view");

  if (!project) {
    return (
      <AppShell projects={projects} username={user.name ?? user.username ?? user.email} role={projectRole ?? user.role} permissions={permissions}>
        <EmptyState title="Create your first property project." href="/projects" actionLabel="Create project" />
      </AppShell>
    );
  }

  const metrics = buildProjectMetrics(project);
  const dashboardFilters = parseExpenseFilters(params);
  const dashboardExpenses = filterExpenses(project.expenses, dashboardFilters);
  const monthlyExpenses = expenseByMonth(dashboardExpenses);
  const weeklyExpenses = expenseByWeek(dashboardExpenses);
  const dailyExpenses = expenseByDay(dashboardExpenses);
  const categoryExpenses = expenseByCategory(dashboardExpenses);
  const investmentPhaseChart = initialInvestmentByPhase(project);
  const operatingExpenseChart = operatingExpensesByMonth(project);
  const partnerChart = partnerBalanceChart(metrics.balances);
  const rentChart = rentByMonth(project);
  const profitLossChart = profitLossByMonth(project);
  const upcomingBillReminders = project.billOccurrences
    .filter((occurrence) => {
      const status = effectiveBillStatus({
        dueDate: occurrence.dueDate,
        lastDateToPay: occurrence.lastDateToPay,
        status: occurrence.status,
        gracePeriodDays: occurrence.recurringBill.gracePeriodDays
      });
      return status !== "PAID" && status !== "SKIPPED" && status !== "ARCHIVED";
    })
    .sort((a, b) => startOfDay(a.dueDate).getTime() - startOfDay(b.dueDate).getTime())
    .slice(0, 8);
  const allProjects = await prisma.project.findMany({
    where: { id: { in: projects.map((item) => item.id) } },
    include: {
      expenses: true,
      rentPayments: true,
      incomes: true,
      operatingExpenses: true
    }
  });
  const allInvested = allProjects.reduce(
    (sum, item) => sum + Number(item.purchasePrice) + item.expenses.reduce((inner, expense) => inner + Number(expense.finalCost), 0),
    0
  );
  const allRentReceived = allProjects.reduce(
    (sum, item) => sum + item.rentPayments.reduce((inner, payment) => inner + Number(payment.rentPaid), 0),
    0
  );
  const allOutstanding = allProjects.reduce(
    (sum, item) => sum + item.rentPayments.reduce((inner, payment) => inner + Math.max(0, Number(payment.balanceDue)), 0),
    0
  );
  const allProfitLoss = allProjects.reduce((sum, item) => {
    const income =
      item.incomes.reduce((inner, income) => inner + Number(income.amount), 0) +
      item.rentPayments.reduce((inner, payment) => inner + Number(payment.rentPaid), 0);
    const expenses = item.operatingExpenses.reduce((inner, expense) => inner + Number(expense.amount), 0);
    return sum + income - expenses;
  }, 0);

  return (
    <AppShell projects={projects} selectedProjectId={project.id} username={user.name ?? user.username ?? user.email} role={projectRole ?? user.role} permissions={permissions}>
      <PageHeader
        title="Dashboard"
        description={`${project.name} is ${project.status.toLowerCase().replace("_", " ")}.`}
        actions={permissions?.["purchaseCosts.create"] ? <Link className="btn-primary" href={`/purchase-costs?projectId=${project.id}`}>Add cost</Link> : null}
      />

      <form className="panel mb-6 grid gap-3 p-4 md:grid-cols-[1fr_1fr_auto]" action="/">
        <input type="hidden" name="projectId" value={project.id} />
        <label className="grid gap-2">
          <span className="label">Chart from</span>
          <input className="field" name="from" type="date" defaultValue={dashboardFilters.from} />
        </label>
        <label className="grid gap-2">
          <span className="label">Chart to</span>
          <input className="field" name="to" type="date" defaultValue={dashboardFilters.to} />
        </label>
        <button className="btn-secondary self-end">Update charts</button>
      </form>

      <section className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
        <StatCard label="Pre-purchase costs" value={metrics.prePurchaseCosts} />
        <StatCard label="Acquisition / closing" value={metrics.acquisitionCosts} />
        <StatCard label="Renovation costs" value={metrics.renovationCosts} />
        <StatCard label="Total initial investment" value={metrics.initialInvestment} tone="warning" />
      </section>

      <section className="mt-6 grid gap-4 md:grid-cols-2 xl:grid-cols-4">
        <StatCard label="Partner contributions" value={metrics.contributionTotal} tone="positive" />
        <StatCard label="Out-of-pocket payments" value={metrics.outOfPocketPartnerPayments} tone="positive" />
        <StatCard label="Project fund payments" value={metrics.projectFundPayments} />
        <StatCard label="Project fund balance" value={metrics.projectFundBalance} tone={metrics.projectFundBalance >= 0 ? "positive" : "warning"} />
      </section>

      <section className="mt-6 grid gap-4 md:grid-cols-2 xl:grid-cols-4">
        <SummaryCard label="Funding records needing review" value={String(metrics.recordsNeedingFundingReview)} detail={metrics.recordsNeedingFundingReview > 0 ? "Open Review Funding" : undefined} />
        <StatCard label="Rent expected this month" value={metrics.rentExpected} />
        <StatCard label="Rent received this month" value={metrics.rentReceived} tone="positive" />
        <StatCard label="Outstanding rent" value={metrics.outstandingRent} tone={metrics.outstandingRent > 0 ? "negative" : "positive"} />
      </section>

      <section className="mt-6 grid gap-4 md:grid-cols-3">
        <StatCard label="Operating profit/loss" value={metrics.profitLoss.netProfitLoss} tone={metrics.profitLoss.netProfitLoss >= 0 ? "positive" : "negative"} />
        <StatCard label="Security deposits held" value={metrics.totalDepositsHeld} />
        <SummaryCard label="Returned / withheld deposits" value={`${currency(metrics.totalDepositsReturned)} / ${currency(metrics.totalDepositsWithheld)}`} />
      </section>

      <section className="mt-6 grid gap-4 md:grid-cols-2 xl:grid-cols-5">
        <SummaryCard label="Bills due this week" value={String(metrics.billsDueThisWeek)} />
        <SummaryCard label="Bills due this month" value={String(metrics.billsDueThisMonth)} />
        <SummaryCard label="Overdue bills" value={String(metrics.overdueBills)} />
        <SummaryCard label="Autopay bills" value={String(metrics.autopayBills)} />
        <SummaryCard label="Expected bills this month" value={metrics.expectedBillsThisMonth} />
      </section>

      <section className="mt-6 grid gap-4 md:grid-cols-2 xl:grid-cols-4">
        <SummaryCard label="Documents" value={String(metrics.totalDocuments)} />
        <SummaryCard label="Needs review" value={String(metrics.documentsNeedingReview)} />
        <SummaryCard label="Expiring soon" value={String(metrics.expiringSoonDocuments)} />
        <SummaryCard label="Expired documents" value={String(metrics.expiredDocuments)} />
      </section>

      <section className="mt-6 grid gap-6 xl:grid-cols-[1.3fr_0.7fr]">
        <div className="panel overflow-hidden">
          <div className="border-b border-line px-4 py-3">
            <h3 className="font-semibold text-ink">Partner Balances</h3>
          </div>
          <div className="overflow-x-auto">
            <table className="w-full min-w-[980px]">
              <thead className="table-head">
                <tr>
                  <th className="px-3 py-2">Partner</th>
                  <th className="px-3 py-2">Ownership</th>
                  <th className="px-3 py-2">Capital Contributed</th>
                  <th className="px-3 py-2">Out-of-Pocket Paid</th>
                  <th className="px-3 py-2">Project Fund Handled</th>
                  <th className="px-3 py-2">Total Credit</th>
                  <th className="px-3 py-2">Responsible Share</th>
                  <th className="px-3 py-2">Net</th>
                </tr>
              </thead>
              <tbody>
                {metrics.balances.map((balance) => (
                  <tr key={balance.partnerId}>
                    <td className="table-cell font-medium text-ink">{balance.name}</td>
                    <td className="table-cell">{balance.ownershipPercentage.toFixed(2)}%</td>
                    <td className="table-cell">{currency(balance.capitalContributed)}</td>
                    <td className="table-cell">{currency(balance.outOfPocketPaid)}</td>
                    <td className="table-cell">{currency(balance.projectFundPaymentsHandled)}</td>
                    <td className="table-cell">{currency(balance.totalPaid)}</td>
                    <td className="table-cell">{currency(balance.totalResponsibleShare)}</td>
                    <td className={`table-cell font-semibold ${balance.netBalance >= 0 ? "text-emerald-700" : "text-red-700"}`}>
                      {currency(balance.netBalance)}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>

        <div className="panel p-4">
          <h3 className="font-semibold text-ink">Settlement</h3>
          <div className="mt-4 grid gap-3">
            {metrics.settlements.length === 0 ? (
              <p className="text-sm text-slate-600">No settlement needed.</p>
            ) : (
              metrics.settlements.map((settlement) => (
                <div key={`${settlement.fromPartnerId}-${settlement.toPartnerId}`} className="rounded-md border border-line bg-slate-50 p-3 text-sm">
                  <span className="font-medium text-red-700">{settlement.fromName}</span> pays{" "}
                  <span className="font-medium text-emerald-700">{settlement.toName}</span>{" "}
                  <span className="font-semibold">{currency(settlement.amount)}</span>
                </div>
              ))
            )}
          </div>
        </div>
      </section>

      <section className="panel mt-6 overflow-hidden">
        <div className="flex flex-col gap-2 border-b border-line px-4 py-3 md:flex-row md:items-center md:justify-between">
          <h3 className="font-semibold text-ink">Bill Reminders</h3>
          <Link className="btn-secondary px-2 py-1 text-xs" href={`/recurring-bills?projectId=${project.id}`}>Open recurring bills</Link>
        </div>
        <div className="overflow-x-auto">
          <table className="w-full">
            <thead className="table-head">
              <tr>
                <th className="px-3 py-2">Bill</th>
                <th className="px-3 py-2">Due</th>
                <th className="px-3 py-2">Last date</th>
                <th className="px-3 py-2">Amount</th>
                <th className="px-3 py-2">Status</th>
              </tr>
            </thead>
            <tbody>
              {upcomingBillReminders.map((occurrence) => {
                  const status = effectiveBillStatus({
                    dueDate: occurrence.dueDate,
                    lastDateToPay: occurrence.lastDateToPay,
                    status: occurrence.status,
                    gracePeriodDays: occurrence.recurringBill.gracePeriodDays
                  });
                  return (
                    <tr key={occurrence.id}>
                      <td className="table-cell">
                        <div className="font-medium text-ink">{occurrence.recurringBill.name}</div>
                        <div className="text-xs text-slate-500">{billTimingMessage({
                          dueDate: occurrence.dueDate,
                          lastDateToPay: occurrence.lastDateToPay,
                          status: occurrence.status,
                          gracePeriodDays: occurrence.recurringBill.gracePeriodDays
                        })}</div>
                      </td>
                      <td className="table-cell">{occurrence.dueDate.toISOString().slice(0, 10)}</td>
                      <td className="table-cell">{occurrence.lastDateToPay ? occurrence.lastDateToPay.toISOString().slice(0, 10) : "-"}</td>
                      <td className="table-cell font-semibold text-ink">{currency(Number(occurrence.amount))}</td>
                      <td className="table-cell">
                        <span className={`inline-flex rounded-md px-2 py-1 text-xs font-semibold ${statusTone(status)}`}>
                          {recurringBillStatusLabels[status]}
                        </span>
                      </td>
                    </tr>
                  );
                })}
            </tbody>
          </table>
          {upcomingBillReminders.length === 0 ? (
            <div className="p-6 text-sm text-slate-600">No recurring bill reminders yet.</div>
          ) : null}
        </div>
      </section>

      <section className="mt-6 grid gap-6 xl:grid-cols-2">
        <ChartPanel title="Initial Investment by Phase">
          <SingleBarChart data={investmentPhaseChart} dataKey="expenses" color="#2563eb" />
        </ChartPanel>
        <ChartPanel title="Operating Expenses by Month">
          <SimpleLineChart data={operatingExpenseChart} dataKey="expenses" />
        </ChartPanel>
        <ChartPanel title="Monthly Cost Trend">
          <SimpleLineChart data={monthlyExpenses} dataKey="expenses" />
        </ChartPanel>
        <ChartPanel title="Weekly Expense Graph">
          <SingleBarChart data={weeklyExpenses} dataKey="expenses" color="#059669" />
        </ChartPanel>
        <ChartPanel title="Daily Expense Graph">
          <SingleBarChart data={dailyExpenses} dataKey="expenses" color="#d97706" />
        </ChartPanel>
        <ChartPanel title="Category-wise Expenses">
          <DistributionPieChart data={categoryExpenses} />
        </ChartPanel>
        <ChartPanel title="Partner Credit vs Share">
          <MultiBarChart data={partnerChart} keys={["paid", "share", "net"]} />
        </ChartPanel>
        <ChartPanel title="Rent Expected vs Received">
          <MultiBarChart data={rentChart} keys={["expected", "received", "outstanding"]} />
        </ChartPanel>
        <ChartPanel title="Rental Profit/Loss Trend">
          <MultiLineChart data={profitLossChart} keys={["income", "expenses", "net"]} />
        </ChartPanel>
        <ChartPanel title="Category Bar Graph">
          <SingleBarChart data={categoryExpenses} dataKey="expenses" color="#7c3aed" />
        </ChartPanel>
      </section>

      <section className="mt-6">
        <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
          <StatCard label="All projects invested" value={allInvested} />
          <StatCard label="All rent received" value={allRentReceived} tone="positive" />
          <StatCard label="All outstanding rent" value={allOutstanding} tone={allOutstanding > 0 ? "negative" : "positive"} />
          <StatCard label="All profit/loss" value={allProfitLoss} tone={allProfitLoss >= 0 ? "positive" : "negative"} />
        </div>
      </section>
    </AppShell>
  );
}
