import { useMemo } from "react";
import { previewAllocation } from "../utils/allocatorPreview";
import { dateStringToUTCMidnight, getBrowserTimezone, isoToDateString } from "../utils/timezone";

type VariableCat = {
  id: string;
  name: string;
  percent: number;
  priority: number;
  isSavings?: boolean;
};

type FixedItem = {
  id: string;
  name: string;
  amountCents: number;
  priority: number;
  dueOn: string;
  autoPayEnabled?: boolean;
};

type OnboardingTrackerProps = {
  step: number;
  budgetCents: number;
  vars: VariableCat[];
  fixeds: FixedItem[];
  incomeType: "regular" | "irregular";
  budgetPeriod?: "weekly" | "biweekly" | "monthly";
  conservatismPercent?: number; // For irregular income: percentage to allocate to fixed expenses
  firstIncomeDate?: Date | string; // For accurate pay period calculation
  userTimezone?: string;
};

const fmtMoney = (cents: number) =>
  new Intl.NumberFormat("en-US", {
    style: "currency",
    currency: "USD",
    maximumFractionDigits: 0,
  }).format((cents ?? 0) / 100);

// Calculate expected funding per paycheck for regular income users
// Count actual pay periods between two dates, matching API logic
function countPayPeriodsBetween(
  startDate: Date,
  endDate: Date,
  firstIncomeDate: Date,
  frequency: "weekly" | "biweekly" | "monthly",
  timezone: string
): number {
  let count = 0;
  let nextPayDate = new Date(firstIncomeDate);

  const targetDay = Number(isoToDateString(firstIncomeDate.toISOString(), timezone).split("-")[2] || "1");
  const advanceByPeriod = () => {
    if (frequency === "monthly") {
      const year = nextPayDate.getUTCFullYear();
      const month = nextPayDate.getUTCMonth() + 1;
      const daysInMonth = new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
      nextPayDate = new Date(Date.UTC(year, month, Math.min(targetDay, daysInMonth)));
    } else {
      const days = frequency === "biweekly" ? 14 : 7;
      nextPayDate = new Date(nextPayDate.getTime() + days * 86_400_000);
    }
  };

  // Advance to the first pay date on or after startDate
  while (nextPayDate < startDate) {
    advanceByPeriod();
  }

  // Count all pay dates up to (but not including) the end date
  while (nextPayDate < endDate) {
    count++;
    advanceByPeriod();
  }
  
  // Ensure at least 1 period to avoid division by zero
  return Math.max(1, count);
}

function calculateExpectedFunding(
  totalCents: number,
  dueDate: string,
  incomeFrequency: "weekly" | "biweekly" | "monthly",
  firstIncomeDate?: Date | string,
  now = new Date(),
  timezone = getBrowserTimezone()
): number {
  const daysPerPaycheck = incomeFrequency === "weekly" ? 7 : incomeFrequency === "biweekly" ? 14 : 30;
  const todayIso = dateStringToUTCMidnight(isoToDateString(now.toISOString(), timezone), timezone);
  const dueIso = dateStringToUTCMidnight(dueDate, timezone);

  const due = new Date(dueIso);
  const userNow = new Date(todayIso);

  let totalPaychecks: number;
  
  if (firstIncomeDate) {
    // Use the same logic as the API: count actual pay dates
    const firstIncomeIso =
      typeof firstIncomeDate === "string"
        ? firstIncomeDate.includes("T")
          ? dateStringToUTCMidnight(isoToDateString(firstIncomeDate, timezone), timezone)
          : dateStringToUTCMidnight(firstIncomeDate, timezone)
        : dateStringToUTCMidnight(isoToDateString(firstIncomeDate.toISOString(), timezone), timezone);
    const firstIncome = new Date(firstIncomeIso);
    totalPaychecks = countPayPeriodsBetween(userNow, due, firstIncome, incomeFrequency, timezone);
  } else {
    // Fallback to simple calculation if firstIncomeDate not provided
    const DAY_MS = 24 * 60 * 60 * 1000;
    const daysUntilDue = Math.max(0, Math.ceil((due.getTime() - userNow.getTime()) / DAY_MS));
    totalPaychecks = Math.max(1, Math.ceil(daysUntilDue / daysPerPaycheck));
  }
  
  // Amount to fund per paycheck - use ceil to match API
  const perPaycheck = Math.ceil(totalCents / totalPaychecks);
  
  return perPaycheck;
}

export default function OnboardingTracker({
  step,
  budgetCents,
  vars,
  fixeds,
  incomeType,
  budgetPeriod = "monthly",
  conservatismPercent = 40,
  firstIncomeDate,
  userTimezone,
}: OnboardingTrackerProps) {
  const timezone = userTimezone || getBrowserTimezone();
  // Only show tracker on steps 4, 5, and 6 (categories, fixed plans, review)
  const shouldShow = step >= 4;
  
  // Calculate totals
  const eligibleFixeds = useMemo(
    () => fixeds.filter((f) => f.autoPayEnabled),
    [fixeds]
  );

  const fixedTotal = useMemo(
    () => eligibleFixeds.reduce((sum, f) => sum + (f.amountCents || 0), 0),
    [eligibleFixeds]
  );
  
  const varsTotal = useMemo(
    () => vars.reduce((sum, v) => sum + (v.percent || 0), 0),
    [vars]
  );
  
  // Preview allocation if we have a budget
  const preview = useMemo(() => {
    if (budgetCents <= 0) return null;
    
    // Convert onboarding data to the format expected by previewAllocation
    const fixedPlans = eligibleFixeds.map(f => {
      let totalCents = f.amountCents;
      let fundedCents = 0;
      
      if (incomeType === "regular" && f.autoPayEnabled) {
        // Regular income: calculate per-paycheck amount based on due date
        totalCents = calculateExpectedFunding(f.amountCents, f.dueOn, budgetPeriod, firstIncomeDate, new Date(), timezone);
      }
      // For irregular income, we pass the full amount as the need
      // The conservatism will be applied by limiting the total budget passed to previewAllocation
      
      return {
        id: f.id,
        name: f.name,
        totalCents,
        fundedCents,
        dueOn: f.dueOn,
        priority: f.priority,
        cycleStart: f.dueOn,
      };
    });
    
    const variableCategories = vars.map(v => ({
      id: v.id,
      name: v.name,
      percent: v.percent,
      balanceCents: 0,
      isSavings: v.isSavings || false,
      priority: v.priority,
    }));
    
    // For irregular income, apply conservatism to split budget between fixed and variable
    if (incomeType === "irregular") {
      const fixedPercentage = conservatismPercent / 100;
      const fixedBudget = Math.floor(budgetCents * fixedPercentage);
      const variableBudget = budgetCents - fixedBudget;
      
      // Allocate fixed budget to fixed plans (by priority)
      const fixedResult = previewAllocation(fixedBudget, fixedPlans, []);
      
      // Allocate remaining budget to variables
      const variableResult = previewAllocation(variableBudget, [], variableCategories);
      
      return {
        fixed: fixedResult.fixed,
        variable: variableResult.variable,
        unallocatedCents: fixedResult.unallocatedCents + variableResult.unallocatedCents,
      };
    }
    
    // For regular income, use standard allocation (fixed first, then variable)
    return previewAllocation(budgetCents, fixedPlans, variableCategories);
  }, [
    budgetCents,
    eligibleFixeds,
    vars,
    incomeType,
    budgetPeriod,
    conservatismPercent,
    firstIncomeDate,
    timezone,
  ]);
  
  // Calculate actual fixed allocation amount from preview
  const fixedAllocated = preview
    ? preview.fixed.reduce((sum, f) => sum + f.amountCents, 0)
    : 0;
  
  const variableAmount = preview
    ? preview.variable.reduce((sum, v) => sum + v.amountCents, 0)
    : budgetCents - fixedTotal;
  
  const isValid = varsTotal === 100 && budgetCents > 0;
  
  if (!shouldShow || budgetCents <= 0) return null;
  
  return (
    <div className="onboarding-tracker">
      <div className="row items-center gap-2 pb-3 border-b border-[--color-ink]/20">
        <div className="w-3 h-3 rounded-full bg-green-500 animate-pulse" />
        <h3 className="font-bold text-sm">Live Budget Tracker</h3>
      </div>
        
        {/* Total Budget */}
        <div className="tracker-section tracker-budget">
          <div className="text-xs muted">Total Budget</div>
          <div className="font-bold text-xl sm:text-2xl font-mono">{fmtMoney(budgetCents)}</div>
          <div className="text-xs text-blue-600 dark:text-blue-400">
            Available to allocate
          </div>
        </div>
        
        {/* Fixed Expenses */}
        <div className="tracker-section tracker-fixed">
          <div className="row items-center justify-between">
            <div className="text-xs muted">Fixed Expenses</div>
            <div className="text-xs font-bold">{eligibleFixeds.length} items</div>
          </div>
          <div className="font-bold text-lg sm:text-xl font-mono">{fmtMoney(fixedTotal)}</div>
          <div className="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2">
            <div
              className="bg-orange-500 h-2 rounded-full transition-all duration-300"
              style={{ width: `${Math.min(100, (fixedAllocated / budgetCents) * 100)}%` }}
            />
          </div>
          <div className="text-xs muted">
          {budgetCents > 0
              ? `${Math.round((fixedAllocated / budgetCents) * 100)}% allocated`
              : "0% of budget"}
          </div>
          
          {/* Individual fixed expenses breakdown */}
          {eligibleFixeds.length > 0 && (
            <div className="tracker-breakdown">
              <div className="text-xs font-semibold mb-1">Breakdown:</div>
              {eligibleFixeds.map((f) => {
                const previewItem = preview?.fixed.find(item => item.id === f.id);
                const totalAmount = f.amountCents;
                const fundedAmount = previewItem?.amountCents || 0;
                
                const fundingPercentage = totalAmount > 0 
                  ? Math.round((fundedAmount / totalAmount) * 100)
                  : 0;
                
                return (
                  <div key={f.id} className="stack gap-1 py-1">
                    <div className="tracker-breakdown-row">
                      <span className="tracker-breakdown-name">
                        {f.name || "Unnamed"}
                      </span>
                      <span className="font-mono text-xs">
                        {fmtMoney(totalAmount)}
                      </span>
                    </div>
                    {f.autoPayEnabled && fundedAmount > 0 && (
                      <div className={`text-xs ${
                        incomeType === "regular" 
                          ? "text-green-700 dark:text-green-600" 
                          : "text-blue-600 dark:text-blue-400"
                      }`}>
                        {incomeType === "regular" ? "Auto" : "Plan"}: {fmtMoney(fundedAmount)} ({fundingPercentage}%)
                      </div>
                    )}
                    {f.autoPayEnabled && fundedAmount === 0 && (
                      <div className="text-xs text-amber-600 dark:text-amber-400">
                        Plan enabled (no funds yet)
                      </div>
                    )}
                  </div>
                );
              })}
            </div>
          )}
        </div>
        
        {/* Variable Categories */}
        <div className="tracker-section tracker-variable">
          <div className="row items-center justify-between">
            <div className="text-xs muted">Variable Budget</div>
            <div className="text-xs font-bold">{vars.length} categories</div>
          </div>
          <div className="font-bold text-lg sm:text-xl font-mono">{fmtMoney(variableAmount)}</div>
          <div className="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2">
            <div
              className="bg-green-500 h-2 rounded-full transition-all duration-300"
              style={{ width: `${Math.min(100, (variableAmount / budgetCents) * 100)}%` }}
            />
          </div>
          <div className="text-xs muted">
            {budgetCents > 0
              ? `${Math.round((variableAmount / budgetCents) * 100)}% of budget`
              : "0% of budget"}
          </div>
          
          {/* Individual variable categories breakdown */}
          {vars.length > 0 && preview && (
            <div className="tracker-breakdown">
              <div className="text-xs font-semibold mb-1">Breakdown:</div>
              {preview.variable.map((item) => {
                const originalVar = vars.find(v => v.id === item.id);
                const percentage = originalVar?.percent || 0;
                
                return (
                  <div key={item.id} className="tracker-breakdown-row py-1">
                    <span className="tracker-breakdown-name">
                      {item.name || "Unnamed"}
                      {originalVar?.isSavings && (
                        <span className="text-green-700 dark:text-green-400 font-bold"> (Savings)</span>
                      )}
                    </span>
                    <span className="font-mono text-xs whitespace-nowrap">
                      {fmtMoney(item.amountCents)} ({percentage}%)
                    </span>
                  </div>
                );
              })}
            </div>
          )}
          
          {/* Percentage validation */}
          <div className="pt-2 border-t border-green-300 dark:border-green-700">
            <div className="row items-center justify-between">
              <span className="text-xs muted">Total percentage:</span>
              <span
                className={`text-xs font-bold ${
                  varsTotal === 100
                    ? "text-green-700 dark:text-green-400"
                    : "text-red-600 dark:text-red-400"
                }`}
              >
                {varsTotal}%
              </span>
            </div>
            {varsTotal !== 100 && (
              <div className="text-xs text-red-600 dark:text-red-400 mt-1">
                Must equal 100%
              </div>
            )}
          </div>
        </div>
        
        {/* Remaining/Unallocated */}
        {preview && preview.unallocatedCents > 0 && (
          <div className="tracker-section bg-gray-50 dark:bg-gray-800/50">
            <div className="text-xs muted">Unallocated</div>
            <div className="font-bold text-lg font-mono text-gray-600 dark:text-gray-400">
              {fmtMoney(preview.unallocatedCents)}
            </div>
          </div>
        )}
        
        {/* Status indicator */}
        <div className={`text-center text-xs p-2 rounded-lg ${
          isValid 
            ? "bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300" 
            : "bg-yellow-100 dark:bg-yellow-900/30 text-yellow-700 dark:text-yellow-300"
        }`}>
          {isValid ? "Ready to continue" : "Complete setup to continue"}
        </div>
    </div>
  );
}
