import React, { useState, useMemo, useEffect } from "react";
import Chart from "./components/Chart";
import InvestmentTable from "./components/InvestmentTable";
import RetirementTable from "./components/RetirementTable";
import SliderInput from "./components/sliderinput";

function getUrlParams() {
  const urlParams = new URLSearchParams(window.location.search);
  return {
    goalAmount: urlParams.get("goalAmount")
      ? parseFloat(urlParams.get("goalAmount"))
      : null,
    targetYears: urlParams.get("targetYears")
      ? parseInt(urlParams.get("targetYears"))
      : null,
    currentAge: urlParams.get("currentAge")
      ? parseInt(urlParams.get("currentAge"))
      : null,
    expectedReturn: urlParams.get("expectedReturn")
      ? parseFloat(urlParams.get("expectedReturn"))
      : null,
    inflationRate: urlParams.get("inflationRate")
      ? parseFloat(urlParams.get("inflationRate"))
      : null,
    initialMonthlyInvestment: urlParams.get("initialMonthlyInvestment")
      ? parseFloat(urlParams.get("initialMonthlyInvestment"))
      : null,
    initialCapital: urlParams.get("initialCapital")
      ? parseFloat(urlParams.get("initialCapital"))
      : null,
    yearsToRetirement: urlParams.get("yearsToRetirement")
      ? parseInt(urlParams.get("yearsToRetirement"))
      : null,
    eventExpenseToday: urlParams.get("eventExpenseToday")
      ? parseFloat(urlParams.get("eventExpenseToday"))
      : null,
    retirementGrowthRate: urlParams.get("retirementGrowthRate")
      ? parseFloat(urlParams.get("retirementGrowthRate"))
      : null,
    pensionInflationRate: urlParams.get("pensionInflationRate")
      ? parseFloat(urlParams.get("pensionInflationRate"))
      : null,
  };
}
export default function App() {
  const urlParams = getUrlParams();

  const [goalAmount, setGoalAmount] = useState(urlParams.goalAmount || 500000);
  const [currentAge, setCurrentAge] = useState(urlParams.currentAge || 35);
  const [expectedReturn, setExpectedReturn] = useState(
    urlParams.expectedReturn || 12
  );
  const [inflationRate, setInflationRate] = useState(
    urlParams.inflationRate || 6
  );
  const [initialMonthlyInvestment, setInitialMonthlyInvestment] = useState(
    urlParams.initialMonthlyInvestment || 500
  );
  const [monthlyIncrement, setMonthlyIncrement] = useState(483);
  const [targetYears, setTargetYears] = useState(urlParams.targetYears || 10);
  const [calculating, setCalculating] = useState(false);
  const [initialCapital, setInitialCapital] = useState(
    urlParams.initialCapital || 0
  );
  const [actualYearsToGoal, setActualYearsToGoal] = useState(10);

  const [yearsToRetirement, setYearsToRetirement] = useState(
    urlParams.yearsToRetirement || 10
  );
  const [eventExpenseToday, setEventExpenseToday] = useState(
    urlParams.eventExpenseToday || 50000
  );
  const [retirementGrowthRate, setRetirementGrowthRate] = useState(
    urlParams.retirementGrowthRate || 10
  );
  const [pensionInflationRate, setPensionInflationRate] = useState(
    urlParams.pensionInflationRate || 6
  );

  const retirementAge = useMemo(() => {
    return currentAge + yearsToRetirement;
  }, [currentAge, yearsToRetirement]);

  const retirementYears = useMemo(() => {
    return 100 - retirementAge + 1;
  }, [retirementAge]);

  const expenseAtTimeOfEvent = useMemo(() => {
    return (
      eventExpenseToday * Math.pow(1 + inflationRate / 100, actualYearsToGoal)
    );
  }, [eventExpenseToday, inflationRate, actualYearsToGoal]);

  const expenseAtStartOfFinancialIndependence = useMemo(() => {
    return (
      eventExpenseToday * Math.pow(1 + inflationRate / 100, yearsToRetirement)
    );
  }, [eventExpenseToday, inflationRate, yearsToRetirement]);

  function calculateSIPFutureValue(monthlyAmount, ratePerAnnum, years) {
    const monthlyRate = Math.pow(1 + ratePerAnnum / 100, 1 / 12) - 1;
    const months = years * 12;

    const futureValue =
      monthlyAmount *
      ((Math.pow(1 + monthlyRate, months) - 1) / monthlyRate) *
      (1 + monthlyRate);

    return parseFloat(futureValue.toFixed(6));
  }

  function calculateCapitalGrowth(capital, ratePerAnnum) {
    return parseFloat((capital * (ratePerAnnum / 100)).toFixed(6));
  }

  function simulateInvestment(increment) {
    let currentMonthlyInvestment = initialMonthlyInvestment;
    let previousYearEndValue = initialCapital;
    let years = 0;

    for (let year = 1; year <= targetYears; year++) {
      const sipFutureValue = calculateSIPFutureValue(
        currentMonthlyInvestment,
        expectedReturn,
        1
      );

      const capitalGrowth = calculateCapitalGrowth(
        previousYearEndValue,
        expectedReturn
      );

      const yearEndValue =
        previousYearEndValue + capitalGrowth + sipFutureValue;

      previousYearEndValue = parseFloat(yearEndValue.toFixed(6));
      currentMonthlyInvestment = parseFloat(
        (currentMonthlyInvestment + increment).toFixed(6)
      );

      years = year;

      if (yearEndValue >= goalAmount) {
        break;
      }
    }

    return {
      finalValue: previousYearEndValue,
      yearsToGoal: years,
    };
  }

  useEffect(() => {
    setCalculating(true);

    const calculateIncrement = () => {
      let minIncrement = -initialMonthlyInvestment;
      let maxIncrement = Math.max(10000, goalAmount / (targetYears * 12));
      let bestIncrement = 0;
      let bestDifference = Infinity;
      let bestYearsToGoal = targetYears;
      let iterations = 0;
      let maxIterations = 300;

      const maxPossibleResult = simulateInvestment(maxIncrement);
      if (maxPossibleResult.finalValue < goalAmount) {
        setMonthlyIncrement(maxIncrement);
        setActualYearsToGoal(targetYears);
        setCalculating(false);
        return;
      }

      while (iterations < maxIterations) {
        iterations++;

        const midIncrement = (minIncrement + maxIncrement) / 2;
        const result = simulateInvestment(midIncrement);
        const finalValue = result.finalValue;
        const yearsToGoal = result.yearsToGoal;
        const difference = Math.abs(finalValue - goalAmount);

        if (difference < bestDifference) {
          bestDifference = difference;
          bestIncrement = midIncrement;
          bestYearsToGoal = yearsToGoal;
        }

        if (difference < 0.01) {
          break;
        }

        if (finalValue < goalAmount) {
          minIncrement = midIncrement;
        } else {
          maxIncrement = midIncrement;
        }

        if (maxIncrement - minIncrement < 0.0001) {
          break;
        }
      }

      let bestAdjustedIncrement = bestIncrement;
      let smallestDifference = Math.abs(
        simulateInvestment(bestIncrement).finalValue - goalAmount
      );
      let finalYearsToGoal = bestYearsToGoal;

      for (let adj = -0.1; adj <= 0.1; adj += 0.0001) {
        const testIncrement = bestIncrement + adj;
        const result = simulateInvestment(testIncrement);
        const testValue = result.finalValue;
        const testYears = result.yearsToGoal;
        const diff = Math.abs(testValue - goalAmount);

        if (diff < smallestDifference) {
          smallestDifference = diff;
          bestAdjustedIncrement = testIncrement;
          finalYearsToGoal = testYears;

          if (diff < 0.001) {
            break;
          }
        }
      }

      setMonthlyIncrement(parseFloat(bestAdjustedIncrement.toFixed(6)));
      setActualYearsToGoal(finalYearsToGoal);
      setCalculating(false);
    };

    const timerId = setTimeout(calculateIncrement, 50);
    return () => clearTimeout(timerId);
  }, [
    goalAmount,
    initialMonthlyInvestment,
    targetYears,
    expectedReturn,
    initialCapital,
  ]);

  const investmentData = useMemo(() => {
    if (calculating) return [];

    const data = [];
    let currentMonthlyInvestment = initialMonthlyInvestment;
    let previousYearEndValue = initialCapital;

    for (let year = 1; year <= targetYears; year++) {
      const age = currentAge + year - 1;
      const monthlySIP = parseFloat(currentMonthlyInvestment.toFixed(6));
      const yearlyInvestment = parseFloat((monthlySIP * 12).toFixed(6));
      const totalInvestible = parseFloat(
        (previousYearEndValue + yearlyInvestment).toFixed(6)
      );

      const sipFutureValue = calculateSIPFutureValue(
        monthlySIP,
        expectedReturn,
        1
      );

      const capitalGrowth = calculateCapitalGrowth(
        previousYearEndValue,
        expectedReturn
      );

      const valueAtYearEnd = parseFloat(
        (previousYearEndValue + capitalGrowth + sipFutureValue).toFixed(6)
      );

      const withdrawal = year === targetYears ? valueAtYearEnd : 0;
      const valueAfterWithdrawal = parseFloat(
        (valueAtYearEnd - withdrawal).toFixed(6)
      );

      data.push({
        year: parseFloat(year.toFixed(3)),
        age: parseFloat(age.toFixed(3)),
        monthlySIP: parseFloat(monthlySIP.toFixed(6)),
        yearlyInvestment: parseFloat(yearlyInvestment.toFixed(6)),
        totalInvestible: parseFloat(totalInvestible.toFixed(6)),
        valueAtYearEnd: parseFloat(valueAtYearEnd.toFixed(6)),
        withdrawal: parseFloat(withdrawal.toFixed(6)),
        valueAfterWithdrawal: parseFloat(valueAfterWithdrawal.toFixed(6)),
      });

      previousYearEndValue = valueAfterWithdrawal;
      currentMonthlyInvestment = parseFloat(
        (currentMonthlyInvestment + monthlyIncrement).toFixed(6)
      );
    }

    return data;
  }, [
    goalAmount,
    currentAge,
    expectedReturn,
    initialMonthlyInvestment,
    monthlyIncrement,
    targetYears,
    calculating,
    initialCapital,
  ]);

  const withdrawalYear =
    investmentData.findIndex((data) => data.withdrawal > 0) + 1;

  const finalValue =
    withdrawalYear > 0 && investmentData.length >= withdrawalYear
      ? investmentData[withdrawalYear - 1].valueAtYearEnd
      : 0;

  const targetMet =
    !calculating && investmentData.some((data) => data.withdrawal > 0);

  const retirementData = useMemo(() => {
    if (!targetMet || finalValue <= 0) return [];

    const data = [];
    const pensionRequiredYears = 100 - retirementAge + 1;
    const yearsToCalculate = pensionRequiredYears;

    let currentMonthlyPension = expenseAtStartOfFinancialIndependence;
    let yearlyWithdrawal = expenseAtStartOfFinancialIndependence * 12;

    const tempData = [];

    for (let year = 1; year <= yearsToCalculate; year++) {
      const age = retirementAge + (year - 1);
      const isLastYear = age === 100;

      if (isLastYear) {
        tempData.push({
          year,
          age,
          corpusAtBeginning: 0,
          monthlyPension: currentMonthlyPension,
          yearlyWithdrawal,
          corpusAfterWithdrawal: 0,
          corpusAtEndOfYear: 0,
          isLastYear: true,
        });
      } else {
        tempData.push({
          year,
          age,
          corpusAtBeginning: 0,
          monthlyPension: currentMonthlyPension,
          yearlyWithdrawal,
          corpusAfterWithdrawal: 0,
          corpusAtEndOfYear: 0,
          isLastYear: false,
        });
      }

      currentMonthlyPension *= 1 + pensionInflationRate / 100;
      yearlyWithdrawal = currentMonthlyPension * 12;
    }

    if (tempData.length > 0) {
      const lastEntry = tempData[tempData.length - 1];
      if (!lastEntry.isLastYear) {
        lastEntry.corpusAtEndOfYear = finalValue;
      } else {
        lastEntry.corpusAfterWithdrawal = 0;
        lastEntry.corpusAtEndOfYear = 0;
      }
    }

    for (let i = tempData.length - 1; i >= 0; i--) {
      const entry = tempData[i];

      if (entry.isLastYear) {
        entry.corpusAtBeginning = entry.yearlyWithdrawal;
      } else {
        entry.corpusAfterWithdrawal =
          entry.corpusAtEndOfYear / (1 + retirementGrowthRate / 100);

        entry.corpusAtBeginning =
          entry.yearlyWithdrawal + entry.corpusAfterWithdrawal;
      }

      if (i > 0) {
        tempData[i - 1].corpusAtEndOfYear = entry.corpusAtBeginning;
      }
    }

    for (let i = 0; i < tempData.length; i++) {
      const entry = tempData[i];

      delete entry.isLastYear;

      entry.corpusAtBeginning = parseFloat(entry.corpusAtBeginning.toFixed(0));
      entry.monthlyPension = parseFloat(entry.monthlyPension.toFixed(0));
      entry.yearlyWithdrawal = parseFloat(entry.yearlyWithdrawal.toFixed(0));
      entry.corpusAfterWithdrawal = parseFloat(
        entry.corpusAfterWithdrawal.toFixed(0)
      );
      entry.corpusAtEndOfYear = parseFloat(entry.corpusAtEndOfYear.toFixed(0));
    }

    return tempData;
  }, [
    targetMet,
    finalValue,
    retirementAge,
    retirementGrowthRate,
    pensionInflationRate,
    expenseAtStartOfFinancialIndependence,
  ]);

  return (
    <div className="w-full min-h-screen bg-gray-50 p-4 md:p-8">
      <div className="max-w-full mx-auto space-y-8">
        <div className="text-center mb-8">
          <h1 className="text-3xl font-bold text-blue-800 mb-2">
            Investment Goal Planner with Step-Up SIP & Retirement Calculator
          </h1>
          <p className="text-gray-600">
            Plan your financial future with optimized monthly investment
            increments and retirement projections
          </p>
        </div>

        <div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
          <div className="lg:col-span-1 bg-white p-6 shadow-lg rounded-lg border border-gray-200">
            <h2 className="text-xl font-bold mb-6 text-gray-800 border-b pb-2">
              Investment Parameters
            </h2>

            <SliderInput
              label="Goal Amount (₹)"
              value={goalAmount}
              onChange={(e) => setGoalAmount(Number(e.target.value))}
              min={10000}
              max={10000000}
              step={1000}
            />

            <SliderInput
              label="Maximum Years to Reach Goal"
              value={targetYears}
              onChange={(e) => setTargetYears(Number(e.target.value))}
              min={1}
              max={30}
              step={1}
            />

            <SliderInput
              label="Current Age"
              value={currentAge}
              onChange={(e) => setCurrentAge(Number(e.target.value))}
              min={18}
              max={50}
              step={1}
            />

            <SliderInput
              label="Expected Return (%)"
              value={expectedReturn}
              onChange={(e) => setExpectedReturn(Number(e.target.value))}
              min={1}
              max={20}
              step={0.1}
            />

            <SliderInput
              label="Inflation Rate (%)"
              value={inflationRate}
              onChange={(e) => setInflationRate(Number(e.target.value))}
              min={0}
              max={15}
              step={0.1}
            />

            <SliderInput
              label="Initial Monthly SIP (₹)"
              value={initialMonthlyInvestment}
              onChange={(e) =>
                setInitialMonthlyInvestment(Number(e.target.value))
              }
              min={500}
              max={50000}
              step={100}
            />

            <h2 className="text-xl font-bold mb-6 mt-8 text-gray-800 border-b pb-2">
              Retirement Parameters
            </h2>

            {/* Updated Retirement Parameter Fields */}
            <SliderInput
              label="Years to Retirement"
              value={yearsToRetirement}
              onChange={(e) => setYearsToRetirement(Number(e.target.value))}
              min={1}
              max={40}
              step={1}
            />

            <SliderInput
              label="Monthly Expense Today (₹)"
              value={eventExpenseToday}
              onChange={(e) => setEventExpenseToday(Number(e.target.value))}
              min={1000}
              max={1000000}
              step={1000}
            />

            <SliderInput
              label="Growth Rate (%)"
              value={retirementGrowthRate}
              onChange={(e) => setRetirementGrowthRate(Number(e.target.value))}
              min={1}
              max={15}
              step={0.1}
            />

            <SliderInput
              label="Pension Inflation Rate (%)"
              value={pensionInflationRate}
              onChange={(e) => setPensionInflationRate(Number(e.target.value))}
              min={0}
              max={15}
              step={0.1}
            />

            <div className="mt-6 p-4 bg-blue-50 rounded-lg border border-blue-200">
              <h3 className="font-semibold text-blue-800 mb-2">
                Calculated Values:
              </h3>
              <div className="space-y-2">
                <div className="flex justify-between items-center">
                  <span className="text-sm text-gray-700">
                    Age at Retirement:
                  </span>
                  <span className="font-semibold">{retirementAge} years</span>
                </div>
                {/* <div className="flex justify-between items-center">
                  <span className="text-sm text-gray-700">
                    Monthly Expense at Retirement:
                  </span>
                  <span className="font-semibold">
                    ₹
                    {Math.round(
                      expenseAtStartOfFinancialIndependence / 12
                    ).toLocaleString()}
                    /month
                  </span>
                </div> */}
                <div className="flex justify-between items-center">
                  <span className="text-sm text-gray-700">
                    Yearly Expense at Retirement:
                  </span>
                  <span className="font-semibold">
                    ₹
                    {Math.round(
                      expenseAtStartOfFinancialIndependence
                    ).toLocaleString()}
                    /year
                  </span>
                </div>
                <div className="flex justify-between items-center">
                  <span className="text-sm text-gray-700">
                    Pension Required for:
                  </span>
                  <span className="font-semibold">{retirementYears} years</span>
                </div>
              </div>
            </div>
          </div>

          <div className="lg:col-span-2">
            <Chart data={investmentData} />

            <div
              className={`mt-6 p-6 rounded-lg shadow-md ${
                calculating
                  ? "bg-gray-100"
                  : targetMet
                  ? "bg-green-50 border border-green-200"
                  : "bg-blue-50 border border-blue-200"
              }`}
            >
              {calculating ? (
                <div className="flex justify-center items-center">
                  <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-700 mr-3"></div>
                  <p className="text-center font-medium text-gray-700">
                    Calculating optimal SIP increment...
                  </p>
                </div>
              ) : (
                <>
                  {calculating ? (
                    <div className="flex justify-center items-center">
                      <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-700 mr-3"></div>
                      <p className="text-center font-medium text-gray-700">
                        Calculating optimal SIP increment...
                      </p>
                    </div>
                  ) : (
                    <>
                      <h3 className="text-lg text-center font-semibold text-blue-800 mb-2">
                        Investment Plan Summary
                      </h3>
                      <p className="text-center font-medium text-black mb-3">
                        With a monthly{" "}
                        {monthlyIncrement >= 0 ? "increment" : "reduction"} of{" "}
                        <span className="text-blue-700 font-semibold">
                          ₹{Math.abs(Math.round(monthlyIncrement * 12))}
                        </span>{" "}
                        (₹{Math.abs(Math.round(monthlyIncrement))}/month), you
                        will reach your goal of{" "}
                        <span className="text-blue-700 font-semibold">
                          ₹{goalAmount.toLocaleString()}
                        </span>{" "}
                        in {withdrawalYear}{" "}
                        {withdrawalYear === 1 ? "year" : "years"}.
                      </p>
                      <div className="flex flex-wrap justify-center gap-8 text-sm">
                        <div className="text-center">
                          <p className="font-semibold text-gray-700">
                            Nominal Goal
                          </p>
                          <p className="text-blue-700 font-bold">
                            ₹{goalAmount.toLocaleString()}
                          </p>
                        </div>
                        <div className="text-center">
                          <p className="font-semibold text-gray-700">
                            Achieved Amount
                          </p>
                          <p className="text-blue-700 font-bold">
                            ₹{Math.round(finalValue).toLocaleString()}
                          </p>
                        </div>
                      </div>
                    </>
                  )}
                </>
              )}
            </div>
          </div>
        </div>

        {!calculating && (
          <div className="mt-8">
            <h2 className="text-xl font-bold mb-4 text-gray-800">
              Year-by-Year Investment Projection
            </h2>
            <InvestmentTable data={investmentData} />
          </div>
        )}

        {!calculating && retirementData.length > 0 && (
          <div className="mt-8">
            <h2 className="text-xl font-bold mb-4 text-gray-800">
              Year-by-Year Retirement Projection
            </h2>
            <div className="flex items-center mb-4 p-4 bg-blue-50 rounded-lg border border-blue-200">
              <div className="bg-blue-100 p-2 rounded-full mr-3">
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  className="h-6 w-6 text-blue-600"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke="currentColor"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth={2}
                    d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
                  />
                </svg>
              </div>
              <div>
                <p className="text-sm text-gray-700">
                  Starting with a corpus of{" "}
                  <span className="font-semibold">
                    ₹{Math.round(finalValue).toLocaleString()}
                  </span>{" "}
                  at age <span className="font-semibold">{retirementAge}</span>,
                  with initial monthly expenses of{" "}
                  <span className="font-semibold">
                    ₹
                    {Math.round(
                      retirementData[0].monthlyPension
                    ).toLocaleString()}
                  </span>
                  , an inflation rate of{" "}
                  <span className="font-semibold">{pensionInflationRate}%</span>{" "}
                  and growth rate of{" "}
                  <span className="font-semibold">{retirementGrowthRate}%</span>
                  .
                </p>
              </div>
            </div>
            <RetirementTable data={retirementData} />
          </div>
        )}
      </div>
    </div>
  );
}
remember this