import React from "react";
import api from "../api.js";
import {useState, useEffect} from "react";

export default function ReportsModule() {
    const username = localStorage.getItem('username');
    const [reports, setReports] = useState([]);
    const [month, setMonth] = useState("");
    const [year, setYear] = useState("");
    const [account, setAccount] = useState("");
    const [accounts, setAccounts] = useState([]);
    const [loading, setLoading] = useState(false);
    const [rates, setRates] = useState({});
    const [loadingRates, setLoadingRates] = useState(false);
    const [grandTotal, setGrandTotal] = useState(0);

    useEffect(() => {
        const fetchAccounts = async () => {
            setLoading(true);
            try {
                const response = await api.get('/accounts/');
                if (response.status === 200) {
                    const sortedAccounts = [...response.data].sort((a, b) => a.store - b.store);
                    setAccounts(sortedAccounts);
                }
            } catch (error) {
                alert(error);
            } finally {
                setLoading(false);
            }
        };
        fetchAccounts();
    }, []);

    const fetchServiceVisits = async () => {
        if (month !== "" && year !== "" && account !== "") {
            setLoading(true);
            try {
                const response = await api.get(
                    `visits/?username=${username}&month=${month}&year=${year}&account=${account}`
                );
                if (response.status === 200) {
                    const sortedVisits = [...response.data].sort((a, b) => {
                        if (a.short_name < b.short_name) return -1;
                        if (a.short_name > b.short_name) return 1;
                        if (a.date < b.date) return -1;
                        if (a.date > b.date) return 1;
                        return 0;
                    });
                    setReports(sortedVisits);

                    setGrandTotal(null); // Reset to null when fetching
                    setRates({});        // Reset rates
                }
            } catch (error) {
                alert(error);
            } finally {
                setLoading(false);
            }
        } else {
            alert("All fields are required!!")
        }
    };

    const fetchRate = async (account) => {
        setLoading(true);
        try {
            const response = await api.post('/accounts/rate/', {'account': account});
            if (response.status === 200) {
                return response.data['rate'];
            }
    } catch (error) {
        alert(error);
        } finally {
            setLoading(false);
        }
    }

    useEffect(() => {
        const fetchAndSetRates = async () => {
            if (reports.length > 0) {
                setLoadingRates(true);
                try {
                    const uniqueAccounts = [...new Set(reports.map(report => report.short_name))];
                    const ratePromises = uniqueAccounts.map(account => fetchRate(account));
                    const fetchedRates = await Promise.all(ratePromises);
                    const ratesObject = {};
                    uniqueAccounts.forEach((account, index) => {
                        ratesObject[account] = fetchedRates[index];
                    });
                    setRates(ratesObject);
                } catch (error) {
                    alert(error); // Handle errors appropriately
                } finally {
                    setLoadingRates(false);
                }
            }
        };
        fetchAndSetRates();
    }, [reports]);

    useEffect(() => {
    if (!loadingRates && Object.keys(rates).length > 0) {
      const closedVisitsData = reports.reduce((count, visit) => {
        if (visit.status === "Closed") {
          count[visit.short_name] = {
            closedVisits: (count[visit.short_name]?.closedVisits || 0) + 1,
            fullName: visit.full_name,
          };
        }
        return count;
      }, {});
      let totalByAccount = 0;
      for (let key in closedVisitsData) {
        if (rates[key] && rates[key] !== "N/A") {
          totalByAccount += closedVisitsData[key].closedVisits * rates[key];
        }
      }
      setGrandTotal(totalByAccount);
    } else if (!loadingRates && reports.length === 0) {
        setGrandTotal(0);
    }
    }, [reports, rates, loadingRates]);

    const handleYear = (e) => {
        setYear(e.target.value)
    }

    const handleMonth = (e) => {
        setMonth(e.target.value)
    }

    const handleAccount = (e) => {
        setAccount(e.target.value)
    }

    // Generate year options dynamically
    const currentYear = new Date().getFullYear();
    const yearOptions = [];
    for (let y = 2024; y <= currentYear + 1; y++) {
        yearOptions.push(y);
    }

    return (
        <div className="d-flex flex-column">
            <div className="d-flex align-items-center justify-content-center p-2">
                <h4>Reports Module</h4>
            </div>
            <div>
                <form className="form-control">
                    <select defaultValue="" onChange={handleYear} className="form-select">
                        <option value="">Select a year...</option>
                        {yearOptions.map(y => (
                            <option key={y} value={y}>{y}</option>
                        ))}
                    </select>
                    <select defaultValue="" required onChange={handleMonth} className="form-select">
                        <option value="">Select a month...</option>
                        <option value="1">January</option>
                        <option value="2">February</option>
                        <option value="3">March</option>
                        <option value="4">April</option>
                        <option value="5">May</option>
                        <option value="6">June</option>
                        <option value="7">July</option>
                        <option value="8">August</option>
                        <option value="9">September</option>
                        <option value="10">October</option>
                        <option value="11">November</option>
                        <option value="12">December</option>
                    </select>
                    <select defaultValue="" required onChange={handleAccount} className="form-select">
                        <option value="">Select an account...</option>
                        <option value="*">*Any*</option>
                        {accounts.map((acc, index) => (<option key={index} value={acc.short_name}>{acc.full_name}</option>))}
                    </select>
                    <button type="button" onClick={fetchServiceVisits} className="btn btn-primary">Fetch Visits</button>
                </form>
                {loading ? <div className="d-flex align-items-center"><h4 className="m-2 p-2">Loading Reports...</h4><div className="m-2 spinner-border"></div></div> : (
                    <div className="d-flex m-2 p-2 flex-column align-items-center justify-content-center">
                        <h4>Closed Visits Detail</h4>
                        <table className="table">
                            <thead>
                            <tr>
                                <th scope="col" className="w-25">Account</th>
                                <th scope="col" className="w-25">Visits</th>
                                <th scope="col" className="w-25">Rate</th>
                                <th scope="col" className="w-25">Total</th>
                            </tr>
                            </thead>
                            <tbody>
                            {Object.entries(
                                reports.reduce(
                                    (count, visit) => {
                                        if (visit.status === "Closed") {
                                            count[visit.short_name] = {
                                                closedVisits: (count[visit.short_name]?.closedVisits || 0) + 1,
                                                fullName: visit.full_name
                                            }
                                        }
                                        return count;
                                    }, {})
                            ).map(
                                ([short_name, count]) => (
                                        <tr key={short_name}>
                                            <th scope="row">{count.fullName}</th>
                                            <td>{count.closedVisits}</td>
                                            <td>{loadingRates ? "Loading..." : (rates[short_name] || "N/A")}</td>
                                            <td>{loadingRates ? "Loading..." : rates[short_name] !== "N/A" ? count.closedVisits * rates[short_name] : "N/A"}</td>
                                        </tr>
                                    )
                                )}
                            <tr>
                                <th colSpan="3">Grand Total:</th>
                                <td>{grandTotal}</td>
                            </tr>
                            </tbody>
                        </table>
                        <h4>Open Visits Detail</h4>
                        <table className="table">
                            <thead>
                            <tr>
                                <th scope="col" className="w-50">Account</th>
                                <th scope="col" className="w-20">Date</th>
                                <th scope="col" className="w-20">Notes</th>
                            </tr>
                            </thead>
                            <tbody>
                            {reports.filter(report => report.status !== 'Closed').map(report => (
                                <tr key={report.id}> {/* Assuming you have an 'id' field */}
                                    <th scope="row">{report.full_name}</th>
                                    <td>{report.date}</td>
                                    <td>{report.notes ? report.notes : null}</td>
                                </tr>
                            ))}
                            </tbody>
                        </table>
                    </div>
                )}
            </div>
        </div>
    )
}
