import {
  Alert,
  Box,
  Button,
  Container,
  Paper,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  TextField,
  Typography,
} from '@mui/material';
import { ReactElement, useEffect, useMemo, useState } from 'react';

const AmoritizationTable = (): ReactElement => {
  const [principal, setPrincipal] = useState<number | ''>('');
  const [annualInterestRate, setAnnualInterestRate] = useState<number | ''>('');
  const [loanTermYears, setLoanTermYears] = useState<number | ''>('');
  const [amortizationSchedule, setAmortizationSchedule] = useState<AmortizationRow[]>([]);
  const [monthlyPayment, setMonthlyPayment] = useState<number>(0);
  const [error, setError] = useState<string | null>(null);

  // Function to calculate the amortization schedule
  const calculateAmortization = () => {
    // Reset error message
    setError(null);

    // Input validation
    if (principal === '' || annualInterestRate === '' || loanTermYears === '') {
      setError('Please fill in all fields.');
      return;
    }
    if (principal <= 0) {
      setError('Principal must be greater than 0.');
      return;
    }
    if (annualInterestRate < 0) {
      setError('Interest rate cannot be negative.');
      return;
    }
    if (loanTermYears <= 0) {
      setError('Loan term must be greater than 0.');
      return;
    }

    const p = Number(principal);
    const annualRate = Number(annualInterestRate);
    const years = Number(loanTermYears);

    const monthlyRate = annualRate / 100 / 12; // Convert annual percentage rate to monthly decimal rate
    const numberOfPayments = years * 12; // Total number of monthly payments

    let calculatedMonthlyPayment = 0;

    // Calculate monthly payment using the loan amortization formula
    if (monthlyRate === 0) {
      // If interest rate is 0, monthly payment is just principal / number of payments
      calculatedMonthlyPayment = p / numberOfPayments;
    } else {
      calculatedMonthlyPayment =
        (p * monthlyRate) / (1 - Math.pow(1 + monthlyRate, -numberOfPayments));
    }

    setMonthlyPayment(calculatedMonthlyPayment);

    const schedule: AmortizationRow[] = [];
    let currentBalance = p;

    // Generate amortization schedule month by month
    for (let i = 1; i <= numberOfPayments; i++) {
      const interestPaid = currentBalance * monthlyRate;
      let principalPaid = calculatedMonthlyPayment - interestPaid;

      // Adjust last payment to account for potential rounding errors
      if (i === numberOfPayments) {
        principalPaid = currentBalance; // Pay off the remaining balance
        calculatedMonthlyPayment = interestPaid + principalPaid; // Adjust last payment amount
      }

      const endingBalance = currentBalance - principalPaid;

      schedule.push({
        month: i,
        startingBalance: currentBalance,
        monthlyPayment: calculatedMonthlyPayment,
        interestPaid: interestPaid,
        principalPaid: principalPaid,
        endingBalance: endingBalance < 0 ? 0 : endingBalance, // Ensure ending balance doesn't go negative
      });

      currentBalance = endingBalance;
    }
    setAmortizationSchedule(schedule);
  };

  // Memoize the total interest paid for display
  const totalInterestPaid = useMemo(() => {
    return amortizationSchedule.reduce((sum, row) => sum + row.interestPaid, 0);
  }, [amortizationSchedule]);

  // Memoize the total principal paid (should be equal to initial principal)
  const totalPrincipalPaid = useMemo(() => {
    return amortizationSchedule.reduce((sum, row) => sum + row.principalPaid, 0);
  }, [amortizationSchedule]);

  // Memoize the total cost of the loan
  const totalCostOfLoan = useMemo(() => {
    return monthlyPayment * (loanTermYears === '' ? 0 : Number(loanTermYears) * 12);
  }, [monthlyPayment, loanTermYears]);

  return (
    <Container maxWidth="lg" sx={{ py: 4 }}>
      <Box sx={{ my: 4, textAlign: 'center' }}>
        <Typography variant="h4" component="h1" gutterBottom sx={{ color: 'background.paper' }}>
          Loan Amortization Calculator
        </Typography>
        <Typography variant="subtitle1" color="text.secondary">
          Calculate your loan payments and see the amortization schedule.
        </Typography>
      </Box>

      <Paper elevation={3} sx={{ p: 4, mb: 4 }}>
        <Box
          component="form"
          sx={{
            display: 'flex',
            flexDirection: { xs: 'column', md: 'row' },
            gap: 3,
            mb: 3,
          }}
          noValidate
          autoComplete="off"
        >
          <TextField
            label="Principal Loan Amount ($)"
            type="number"
            value={principal}
            onChange={(e) => setPrincipal(e.target.value === '' ? '' : Number(e.target.value))}
            fullWidth
            variant="outlined"
            inputProps={{ min: 0 }}
          />
          <TextField
            label="Annual Interest Rate (%)"
            type="number"
            value={annualInterestRate}
            onChange={(e) =>
              setAnnualInterestRate(e.target.value === '' ? '' : Number(e.target.value))
            }
            fullWidth
            variant="outlined"
            inputProps={{ min: 0 }}
          />
          <TextField
            label="Loan Term (Years)"
            type="number"
            value={loanTermYears}
            onChange={(e) => setLoanTermYears(e.target.value === '' ? '' : Number(e.target.value))}
            fullWidth
            variant="outlined"
            inputProps={{ min: 0 }}
          />
        </Box>
        <Button
          variant="contained"
          color="primary"
          onClick={calculateAmortization}
          fullWidth
          size="large"
        >
          Calculate Amortization
        </Button>
        {error && (
          <Alert severity="error" sx={{ mt: 2, borderRadius: 2 }}>
            {error}
          </Alert>
        )}
      </Paper>

      {amortizationSchedule.length > 0 && (
        <Paper elevation={3} sx={{ p: 4 }}>
          <Typography variant="h5" gutterBottom sx={{ mb: 2 }}>
            Summary
          </Typography>
          <Box sx={{ mb: 3 }}>
            <Typography variant="h6">Monthly Payment: ${monthlyPayment.toFixed(2)}</Typography>
            <Typography variant="body1">
              Total Principal Paid: ${totalPrincipalPaid.toFixed(2)}
            </Typography>
            <Typography variant="body1">
              Total Interest Paid: ${totalInterestPaid.toFixed(2)}
            </Typography>
            <Typography variant="body1">
              Total Cost of Loan: ${totalCostOfLoan.toFixed(2)}
            </Typography>
          </Box>

          <Typography variant="h5" gutterBottom sx={{ mb: 2 }}>
            Amortization Schedule
          </Typography>
          <TableContainer component={Paper} sx={{ maxHeight: 600, overflow: 'auto' }}>
            <Table stickyHeader aria-label="amortization table">
              <TableHead>
                <TableRow>
                  <TableCell>Month</TableCell>
                  <TableCell align="right">Starting Balance</TableCell>
                  <TableCell align="right">Monthly Payment</TableCell>
                  <TableCell align="right">Interest Paid</TableCell>
                  <TableCell align="right">Principal Paid</TableCell>
                  <TableCell align="right">Ending Balance</TableCell>
                </TableRow>
              </TableHead>
              <TableBody>
                {amortizationSchedule.map((row) => (
                  <TableRow key={row.month}>
                    <TableCell component="th" scope="row">
                      {row.month}
                    </TableCell>
                    <TableCell align="right">${row.startingBalance.toFixed(2)}</TableCell>
                    <TableCell align="right">${row.monthlyPayment.toFixed(2)}</TableCell>
                    <TableCell align="right">${row.interestPaid.toFixed(2)}</TableCell>
                    <TableCell align="right">${row.principalPaid.toFixed(2)}</TableCell>
                    <TableCell align="right">${row.endingBalance.toFixed(2)}</TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </TableContainer>
        </Paper>
      )}
    </Container>
  );
};

export default AmoritizationTable;
