import Link from "next/link";
import { and, desc, eq } from "drizzle-orm";
import { requireSession } from "@/lib/auth";
import { db } from "@/db";
import { customers, customerClassifications } from "@/db/schema";
import { FocusSelect } from "@/components/focus-select";
import { loadFocusOptions, withFocus, parseFocus } from "@/lib/focus";
import { coreMetrics, customerScope, customerTargetProgress, debtSummary, dealerTierDistribution, kpiForPeriod, salesLeaderboard, targetFor, type LeaderboardSort } from "@/lib/reports";
import { monthlyTrend, planVsActual, productReport, promoReport, salesOverview, shareByTree, staffingReport, type Dimension } from "@/lib/sales-analysis";
import { isRealMonth, monthKey, monthsInPeriod, periodElapsed, periodRange, quarterOfMonth, shiftMonth, today } from "@/lib/period";
import { formatDate, formatPercent, formatPeriod, formatVndShort, STAGE_LABEL } from "@/lib/format";
import { EmptyState, PageHeader, ProgressBar, SectionTitle, TableWrap } from "@/components/ui";
import { CustomerOverviewCards, CustomerRankingView, NewCustomersView, OverviewView, PlanView, ProductShareView, ProductView, PromoView, RankingView, StaffShareView, StaffingView, TreeShareView } from "./views";
import { CUSTOMER_RANK_SORTS, CUSTOMER_STAGE_FILTERS, customerOverview, customerRanking, newCustomerList, newCustomersByGroup, type CustomerStageFilter } from "@/lib/customer-report";

export const dynamic = "force-dynamic";

const SECTIONS = [
  { key: "tong-quan", label: "Tổng quan" },
  { key: "ke-hoach", label: "Kế hoạch" },
  { key: "ty-trong", label: "Tỷ trọng" },
  { key: "xep-hang", label: "Xếp hạng NV" },
  { key: "khach-hang", label: "Khách hàng" },
  { key: "san-pham", label: "Sản phẩm" },
  { key: "khuyen-mai", label: "Khuyến mãi" },
  { key: "dinh-bien", label: "Định biên" },
] as const;
type Section = (typeof SECTIONS)[number]["key"];

const PLAN_DIMENSIONS: { key: Dimension; label: string }[] = [
  { key: "khu-vuc", label: "Khu vực" },
  { key: "phong-ban", label: "Phòng ban / Team" },
  { key: "nhan-vien", label: "Nhân viên" },
];
const SHARE_DIMENSIONS = [...PLAN_DIMENSIONS, { key: "san-pham", label: "Sản phẩm" }] as const;
type ShareDimension = (typeof SHARE_DIMENSIONS)[number]["key"];

/** Chấp nhận '2026-08' (tháng có thật), '2026-Q3' hoặc '2026'. */
function isValidPeriod(value?: string): value is string {
  return Boolean(value && (isRealMonth(value) || /^\d{4}-Q[1-4]$/.test(value) || /^\d{4}$/.test(value)));
}

/** Kỳ liền trước cùng loại: tháng → tháng trước, quý → quý trước, năm → năm trước. */
function previousPeriod(period: string): string {
  if (/^\d{4}$/.test(period)) return String(Number(period) - 1);
  const quarter = period.match(/^(\d{4})-Q([1-4])$/);
  if (quarter) return Number(quarter[2]) === 1 ? `${Number(quarter[1]) - 1}-Q4` : `${quarter[1]}-Q${Number(quarter[2]) - 1}`;
  return shiftMonth(period, 1);
}

export default async function AnalyticsPage({
  searchParams,
}: {
  searchParams: Promise<{ ky?: string; xh?: string; pv?: string; muc?: string; dv?: string; kh?: string; lk?: string; xk?: string; trang?: string }>;
}) {
  const baseSession = await requireSession();
  const params = await searchParams;

  // Phân tích là báo cáo quản trị (số liệu cả đội) — nhân viên kinh doanh xem báo cáo của mình ở mục Báo cáo.
  if (baseSession.role === "SALES") {
    return (
      <>
        <PageHeader title="Phân tích bán hàng" />
        <EmptyState message="Bạn không có quyền xem trang phân tích." hint="Dành cho Ban giám đốc, Giám đốc khu vực và Quản lý. Số liệu của bạn ở mục Báo cáo." action={{ href: "/bao-cao", label: "Mở báo cáo của tôi" }} />
      </>
    );
  }

  const session = withFocus(baseSession, params.pv);
  const focusOptions = await loadFocusOptions(baseSession);
  const pvValue = parseFocus(params.pv) ? params.pv! : "";

  /* Kỳ phân tích nhận cả ba dạng: '2026-08' (tháng), '2026-Q3' (quý), '2026' (năm) — yêu cầu "phân tích tháng/quý/năm". */
  const period = isValidPeriod(params.ky) ? params.ky : monthKey(today());
  const section: Section = SECTIONS.some((s) => s.key === params.muc) ? (params.muc as Section) : "tong-quan";
  const leaderSort: LeaderboardSort = (["doanhthu", "doanhso", "no", "moi"] as const).find((k) => k === params.xh) ?? "doanhthu";
  const planDimension: Dimension = PLAN_DIMENSIONS.find((d) => d.key === params.dv)?.key ?? "khu-vuc";
  const shareDimension: ShareDimension = SHARE_DIMENSIONS.find((d) => d.key === params.dv)?.key ?? "khu-vuc";
  // Mục Khách hàng: loại khách (lk), mục con (kh), tiêu chí xếp hạng khách (xk), số trang.
  const stageFilter: CustomerStageFilter = (CUSTOMER_STAGE_FILTERS as readonly string[]).includes(params.lk ?? "") ? (params.lk as CustomerStageFilter) : "";
  const customerView = params.kh === "moi" ? "moi" : "xep-hang";
  const customerSort = CUSTOMER_RANK_SORTS.find((k) => k === params.xk) ?? "doanhthu";
  const pageParam = Number(params.trang);
  const wantedPage = Number.isInteger(pageParam) && pageParam >= 1 && pageParam <= 10_000 ? pageParam : 1;
  const range = periodRange(period);
  const monthsOfPeriod = monthsInPeriod(period);
  const anchorMonth = monthsOfPeriod[monthsOfPeriod.length - 1];

  const { elapsed, total } = periodElapsed(period);
  const periodBenchmark = total > 0 ? (elapsed / total) * 100 : 0;

  const href = (patch: Record<string, string> = {}) => {
    const next: Record<string, string> = { ky: period, pv: pvValue, muc: section, lk: stageFilter, ...patch };
    const qs = new URLSearchParams();
    for (const [key, value] of Object.entries(next)) {
      if (!value || (key === "muc" && value === "tong-quan")) continue;
      qs.set(key, value);
    }
    const text = qs.toString();
    return text ? `/phan-tich?${text}` : "/phan-tich";
  };
  const exportHref = `/api/xuat-excel?loai=phan-tich&ky=${period}${pvValue ? `&pv=${pvValue}` : ""}${section === "xep-hang" && leaderSort !== "doanhthu" ? `&xh=${leaderSort}` : ""}${section === "khach-hang" && customerSort !== "doanhthu" ? `&xk=${customerSort}` : ""}${stageFilter ? `&lk=${stageFilter}` : ""}`;
  // Hồ sơ nhân viên mở đúng kỳ đang xem: kỳ đang chạy lấy hôm nay, kỳ đã qua lấy ngày cuối kỳ.
  const nowIso = today();
  const profileAnchor = nowIso >= range.start && nowIso <= range.end ? nowIso : range.end < nowIso ? range.end : range.start;
  const profileTab = period.length === 4 ? "nam" : /Q/.test(period) ? "quy" : "thang";
  const profileHref = (id: string) => `/danh-muc/nguoi-dung/${id}?ky=${profileTab}&ngay=${profileAnchor}`;
  const periodOptions = buildPeriodOptions(today());

  /* Chỉ tải dữ liệu của mục đang xem — mỗi mục là một nhóm truy vấn riêng, gộp hết vào một lần tải sẽ chậm không cần thiết. */
  let body: React.ReactNode;

  if (section === "tong-quan") {
    const [overview, previous, target, debt, staffing, trend, regionShare, tiers, keyDealers, promo] = await Promise.all([
      salesOverview(session, range),
      salesOverview(session, periodRange(previousPeriod(period))),
      targetFor(session, period),
      debtSummary(session, range, today()),
      staffingReport(session, period),
      monthlyTrend(session, period.slice(0, 4)),
      shareByTree(session, range, "khu-vuc"),
      dealerTierDistribution(session, anchorMonth),
      db
        .select({
          id: customers.id,
          orgName: customers.orgName,
          code: customers.code,
          tier: customerClassifications.revenueTier,
          avgRevenue: customerClassifications.avgMonthlyRevenue,
          skuCount: customerClassifications.skuCount,
        })
        .from(customerClassifications)
        .innerJoin(customers, eq(customerClassifications.customerId, customers.id))
        .where(
          and(
            eq(customerClassifications.tenantId, session.tenantId),
            eq(customerClassifications.periodKey, anchorMonth),
            eq(customers.isKey, true),
            // Chỉ đại lý trong phạm vi người xem — trước đây thiếu điều kiện này nên đại lý Key của mọi khu vực đều hiện.
            await customerScope(session),
          ),
        )
        .orderBy(desc(customerClassifications.avgMonthlyRevenue))
        .limit(8),
      promoReport(session, range),
    ]);
    body = (
      <OverviewView
        period={period}
        overview={overview}
        previousRevenue={previous.revenue}
        target={target}
        debt={debt}
        promoValue={promo.totals.value}
        staffing={staffing.overall}
        trend={trend}
        regionShare={regionShare.rows}
        tiers={tiers.map((t) => ({ tier: t.tier, count: t.count }))}
        keyDealers={keyDealers.map((d) => ({ ...d, avgRevenue: Number(d.avgRevenue) }))}
      />
    );
  } else if (section === "ke-hoach") {
    const [plan, kpis, customerTargets] = await Promise.all([planVsActual(session, period, planDimension), kpiForPeriod(session, period), customerTargetProgress(session, period)]);
    // Người chưa được giao chỉ tiêu và chưa có đơn (ví dụ quản lý không bán hàng) không có gì để so — không đưa vào bảng KPI.
    const kpiRows = kpis.filter((k) => Number(k.revenueTarget) > 0 || Number(k.revenue) > 0 || k.orderCount > 0);
    body = (
      <>
        <SubTabs items={PLAN_DIMENSIONS} current={planDimension} hrefFor={(key) => href({ dv: key })} />
        <PlanView plan={plan} benchmark={periodBenchmark} dimensionLabel={PLAN_DIMENSIONS.find((d) => d.key === planDimension)!.label} />

        <div className="mt-8">
          <SectionTitle hint="thực hiện so với chỉ tiêu được giao">KPI {formatPeriod(period).toLowerCase()} từng NVKD</SectionTitle>
          <TableWrap>
            <thead>
              <tr>
                <th>Nhân viên</th>
                <th className="text-right">Doanh thu</th>
                <th className="text-right">Chỉ tiêu</th>
                <th style={{ width: 140 }}>% Hoàn thành</th>
                <th className="text-right">Số đơn</th>
                <th className="text-right">Lượt viếng thăm</th>
                <th className="text-right">% Bám kế hoạch</th>
                <th className="text-right">ĐL hoạt động</th>
              </tr>
            </thead>
            <tbody>
              {kpiRows.length === 0 && (
                <tr>
                  <td colSpan={8} className="py-8 text-center text-ink-400">
                    Chưa có số liệu KPI cho kỳ này. Chạy <code>npm run jobs:nightly</code> để tính lại.
                  </td>
                </tr>
              )}
              {kpiRows.map((row) => (
                <tr key={row.userId}>
                  <td>
                    <Link href={profileHref(row.userId)} className="font-medium text-ink-700 hover:text-brand-600">
                      {row.fullName}
                    </Link>
                  </td>
                  <td className="tnum text-right">{formatVndShort(Number(row.revenue))}</td>
                  <td className="tnum text-right text-ink-400">{Number(row.revenueTarget) > 0 ? formatVndShort(Number(row.revenueTarget)) : "—"}</td>
                  <td>
                    <div className="tnum mb-1 text-xs font-semibold text-ink-600">{row.achievementPct > 0 ? `${row.achievementPct}%` : "—"}</div>
                    {row.achievementPct > 0 && <ProgressBar percent={row.achievementPct} benchmark={periodBenchmark} />}
                  </td>
                  <td className="tnum text-right text-ink-500">{row.orderCount}</td>
                  <td className="tnum text-right text-ink-500">{row.visitCount}</td>
                  <td className="tnum text-right text-ink-500">{row.planCompliancePct}%</td>
                  <td className="tnum text-right text-ink-500">{row.activeDealerCount}</td>
                </tr>
              ))}
            </tbody>
          </TableWrap>
        </div>

        {customerTargets.length > 0 && (
          <div className="mt-8">
            <SectionTitle hint={`${customerTargets.length} đại lý được giao chỉ tiêu`}>Thực hiện so với kế hoạch theo khách hàng</SectionTitle>
            <TableWrap>
              <thead>
                <tr>
                  <th>Đại lý</th>
                  <th>Khu vực · NVKD</th>
                  <th className="text-right">Thực hiện</th>
                  <th className="text-right">Kế hoạch</th>
                  <th style={{ width: 140 }}>% Hoàn thành</th>
                  <th className="text-right">Số đơn</th>
                </tr>
              </thead>
              <tbody>
                {customerTargets.map((row) => (
                  <tr key={row.customerId}>
                    <td>
                      <Link href={`/khach-hang/${row.customerId}`} className="font-medium text-ink-700 hover:text-brand-600">
                        {row.orgName}
                      </Link>
                      <div className="text-[11px] text-ink-400">{row.code}</div>
                    </td>
                    <td className="text-ink-500">
                      <div>{row.territoryName ?? "—"}</div>
                      <div className="text-[11px] text-ink-400">{row.ownerName ?? "—"}</div>
                    </td>
                    <td className="tnum text-right font-medium">{formatVndShort(row.revenue)}</td>
                    <td className="tnum text-right text-ink-400">{formatVndShort(row.revenueTarget)}</td>
                    <td>
                      <div className="tnum mb-1 text-xs font-semibold text-ink-600">{row.achievementPct != null ? formatPercent(row.achievementPct) : "—"}</div>
                      {row.achievementPct != null && <ProgressBar percent={row.achievementPct} benchmark={periodBenchmark} />}
                    </td>
                    <td className="tnum text-right text-ink-500">{row.orderCount || "—"}</td>
                  </tr>
                ))}
              </tbody>
            </TableWrap>
            <p className="mt-2 text-xs text-ink-400">Chỉ hiện những đại lý trong phạm vi của bạn đã được giao chỉ tiêu ở Danh mục → Giao chỉ tiêu.</p>
          </div>
        )}
      </>
    );
  } else if (section === "ty-trong") {
    let inner: React.ReactNode;
    if (shareDimension === "nhan-vien") {
      const leaderboard = await salesLeaderboard(session, range, "doanhthu");
      inner = <StaffShareView rows={leaderboard} profileHref={profileHref} rankingHref={href({ muc: "xep-hang", dv: "" })} />;
    } else if (shareDimension === "san-pham") {
      const report = await productReport(session, range);
      inner = <ProductShareView rows={report.rows} total={report.total} />;
    } else {
      const share = await shareByTree(session, range, shareDimension);
      inner = <TreeShareView rows={share.rows} total={share.total} label={shareDimension === "khu-vuc" ? "Khu vực" : "Phòng ban / Team"} />;
    }
    body = (
      <>
        <SubTabs items={SHARE_DIMENSIONS} current={shareDimension} hrefFor={(key) => href({ dv: key })} />
        {inner}
      </>
    );
  } else if (section === "xep-hang") {
    const [leaderboard, plan, core] = await Promise.all([salesLeaderboard(session, range, leaderSort), planVsActual(session, period, "nhan-vien"), coreMetrics(session, range)]);
    body = (
      <RankingView
        rows={leaderboard}
        sort={leaderSort}
        sortLinks={(["doanhthu", "doanhso", "no", "moi"] as const).map((key) => ({ key, href: href({ xh: key === "doanhthu" ? "" : key, dv: "" }) }))}
        plan={new Map(plan.rows.map((r) => [r.id, { target: r.target, pct: r.pct }]))}
        profileHref={profileHref}
        benchmark={periodBenchmark}
        unassignedNew={Math.max(0, core.newCustomerCount - leaderboard.reduce((sum, r) => sum + r.newCustomers, 0))}
      />
    );
  } else if (section === "khach-hang") {
    const overview = await customerOverview(session, range, stageFilter);
    const stageChips = (
      <div className="mb-4 flex flex-wrap items-center gap-1.5 text-sm">
        <span className="label-caps mr-1">Loại khách</span>
        {([["", "Tất cả"], ["DEALER", STAGE_LABEL.DEALER], ["PROSPECT", STAGE_LABEL.PROSPECT], ["LEAD", STAGE_LABEL.LEAD]] as const).map(([key, label]) => (
          <Link key={key} href={href({ lk: key, trang: "" })} className={`rounded-full border px-3 py-1 font-semibold ${stageFilter === key ? "border-brand-500 bg-brand-500 text-white" : "border-[var(--color-line)] bg-white text-ink-500 hover:bg-ink-50"}`}>
            {label}
          </Link>
        ))}
      </div>
    );
    let inner: React.ReactNode;
    if (customerView === "xep-hang") {
      const ranking = await customerRanking(session, range, period, stageFilter, customerSort, { page: wantedPage });
      const topRows = ranking.page === 1 ? ranking.rows : (await customerRanking(session, range, period, stageFilter, customerSort, { page: 1, pageSize: 10 })).rows;
      const valueKey = { doanhthu: "revenue", doanhso: "sales", no: "debt" }[customerSort] as "revenue" | "sales" | "debt";
      inner = (
        <CustomerRankingView
          ranking={ranking}
          sort={customerSort}
          sortLinks={CUSTOMER_RANK_SORTS.map((key) => ({ key, href: href({ kh: "", xk: key === "doanhthu" ? "" : key, trang: "" }) }))}
          pageHref={(n) => href({ kh: "", xk: customerSort === "doanhthu" ? "" : customerSort, trang: n > 1 ? String(n) : "" })}
          chartRows={topRows.slice(0, 10).map((r) => ({ name: r.orgName, value: r[valueKey] }))}
        />
      );
    } else {
      const [groups, list] = await Promise.all([newCustomersByGroup(session, range, stageFilter, planDimension), newCustomerList(session, range, stageFilter, { page: wantedPage })]);
      inner = (
        <>
          <SubTabs items={PLAN_DIMENSIONS} current={planDimension} hrefFor={(key) => href({ kh: "moi", dv: key, trang: "" })} />
          <NewCustomersView groups={groups} groupLabel={PLAN_DIMENSIONS.find((d) => d.key === planDimension)!.label} list={list} periodLabel={formatPeriod(period)} pageHref={(n) => href({ kh: "moi", dv: planDimension, trang: n > 1 ? String(n) : "" })} />
        </>
      );
    }
    body = (
      <>
        <CustomerOverviewCards overview={overview} periodLabel={formatPeriod(period)} />
        <div className="mt-5" />
        {stageChips}
        <SubTabs
          items={[{ key: "xep-hang", label: "Xếp hạng khách hàng" }, { key: "moi", label: "Khách hàng mở mới" }] as const}
          current={customerView}
          hrefFor={(key) => href({ kh: key === "moi" ? "moi" : "", dv: "", trang: "" })}
        />
        {inner}
      </>
    );
  } else if (section === "san-pham") {
    const report = await productReport(session, range);
    body = <ProductView rows={report.rows} total={report.total} totalSales={report.totalSales} />;
  } else if (section === "khuyen-mai") {
    body = <PromoView promo={await promoReport(session, range)} />;
  } else {
    body = <StaffingView staffing={await staffingReport(session, period)} />;
  }

  const focusLabel = focusOptions && pvValue ? describeFocus(focusOptions, pvValue) : null;

  return (
    <>
      <PageHeader
        title="Phân tích bán hàng"
        subtitle={`${formatPeriod(period)} (${formatDate(range.start)} → ${formatDate(range.end)})${focusLabel ? ` · ${focusLabel}` : " · toàn bộ phạm vi của bạn"}`}
        actions={
          <>
            <form action="/phan-tich" className="flex flex-wrap items-end gap-2">
              <input type="hidden" name="muc" value={section} />
              {params.dv && <input type="hidden" name="dv" value={params.dv} />}
              {section === "xep-hang" && leaderSort !== "doanhthu" && <input type="hidden" name="xh" value={leaderSort} />}
              {section === "khach-hang" && params.kh && <input type="hidden" name="kh" value={params.kh} />}
              {section === "khach-hang" && customerSort !== "doanhthu" && <input type="hidden" name="xk" value={customerSort} />}
              {section === "khach-hang" && stageFilter && <input type="hidden" name="lk" value={stageFilter} />}
              <FocusSelect options={focusOptions} value={pvValue} />
              <select name="ky" defaultValue={period} className="input" aria-label="Chọn kỳ phân tích">
                <optgroup label="Tháng">
                  {periodOptions.months.map((key) => (
                    <option key={key} value={key}>
                      {formatPeriod(key)}
                    </option>
                  ))}
                </optgroup>
                <optgroup label="Quý">
                  {periodOptions.quarters.map((key) => (
                    <option key={key} value={key}>
                      {formatPeriod(key)}
                    </option>
                  ))}
                </optgroup>
                <optgroup label="Năm">
                  {periodOptions.years.map((key) => (
                    <option key={key} value={key}>
                      {formatPeriod(key)}
                    </option>
                  ))}
                </optgroup>
              </select>
              <button type="submit" className="btn-ghost">
                Xem
              </button>
            </form>
            <a href={exportHref} className="btn-ghost" download>
              Xuất Excel
            </a>
          </>
        }
      />

      <div className="mb-5 flex gap-1 overflow-x-auto rounded-lg border border-[var(--color-line)] bg-white p-1">
        {SECTIONS.map((item) => (
          <Link
            key={item.key}
            href={href({ muc: item.key, dv: "", xh: "", lk: "", kh: "", xk: "", trang: "" })}
            className={`shrink-0 rounded-md px-3 py-1.5 text-sm font-semibold ${section === item.key ? "bg-brand-500 text-white" : "text-ink-500 hover:bg-ink-50"}`}
          >
            {item.label}
          </Link>
        ))}
      </div>

      {body}
    </>
  );
}

/** Nút chọn chiều xem (khu vực / phòng ban / nhân viên / sản phẩm) trong một mục. */
function SubTabs<T extends string>({ items, current, hrefFor }: { items: readonly { key: T; label: string }[]; current: T; hrefFor: (key: T) => string }) {
  return (
    <div className="mb-4 flex w-fit flex-wrap gap-1 rounded-lg border border-[var(--color-line)] bg-white p-1">
      {items.map((item) => (
        <Link key={item.key} href={hrefFor(item.key)} className={`rounded-md px-3 py-1.5 text-sm font-semibold ${current === item.key ? "bg-ink-700 text-white" : "text-ink-500 hover:bg-ink-50"}`}>
          {item.label}
        </Link>
      ))}
    </div>
  );
}

function describeFocus(options: NonNullable<Awaited<ReturnType<typeof loadFocusOptions>>>, value: string): string | null {
  const [type, id] = value.split(":");
  const list = type === "terr" ? options.territories : type === "dept" ? options.departments : options.users;
  const found = list.find((item) => item.id === id);
  return found ? `${type === "terr" ? "Khu vực" : type === "dept" ? "Phòng/Team" : "Nhân viên"}: ${found.name}` : null;
}

/**
 * Danh sách kỳ cho ô chọn: 12 tháng gần nhất, 4 quý gần nhất, 2 năm gần nhất.
 * Dùng một ô chọn duy nhất thay vì ba loại ô riêng — người dùng chỉ cần chọn kỳ,
 * không cần trước đó phải chọn "loại kỳ".
 */
function buildPeriodOptions(anchorDate: string) {
  const currentMonth = monthKey(anchorDate);
  const currentYear = Number(anchorDate.slice(0, 4));

  const months = Array.from({ length: 12 }, (_, i) => shiftMonth(currentMonth, i));

  const quarters: string[] = [];
  let cursor = currentMonth;
  while (quarters.length < 4) {
    const quarter = quarterOfMonth(cursor);
    if (!quarters.includes(quarter)) quarters.push(quarter);
    cursor = shiftMonth(cursor, 1);
  }

  const years = [String(currentYear), String(currentYear - 1)];

  return { months, quarters, years };
}
