import type {Route} from "../../../.react-router/types/app/pages/dashboard/+types/PatientsManagement";
import {useEffect, useMemo, useState} from "react";
import {DashboardPageType, UserType} from "~/utils/hms_enums.ts";
import {useNavigate, useOutletContext} from "react-router";
import {
    type DoctorTeamInfo,
    type OutletContextType,
    type PatientDataWithWardAndAdmission,
    SORT_SYMBOLS,
    type WardInfo
} from "~/utils/models.ts";
import {Accordion, ActionIcon, Button, Card, Group, Pagination, Stack, Table, Text, Tooltip} from "@mantine/core";
import {apiGetPatientsList, apiGetTeamList, apiGetWardList} from "~/utils/hms_api.ts";
import {showErrorMessage} from "~/utils/utils.ts";
import {iconMStyle, marginLeftRight, marginRightBottom, marginTopBottom} from "~/styles.ts";
import PencilIcon from "mdi-react/PencilIcon";
import LogoutVariantIcon from "mdi-react/LogoutVariantIcon";
import AddIcon from "mdi-react/AddIcon";
import InfoIcon from "mdi-react/InfoIcon";
import {
    confirmAdminAddUser,
    confirmCheckWardPatients,
    confirmEditPatient,
    confirmPatientDischarge,
    confirmResetPassword
} from "~/components/subs/confirms.tsx";
import {PatientManagementFilter} from "~/components/subs/PatientManagementFilter.tsx";
import {PatientInfoDisplay} from "~/components/subs/PatientInfoDisplay.tsx";
import {TeamInfoDisplay} from "~/components/subs/TeamInfoDisplay.tsx";
import LockResetIcon from "mdi-react/LockResetIcon";
import {modals} from "@mantine/modals";
import HistoryIcon from "mdi-react/HistoryIcon";
import FilterIcon from "mdi-react/FilterIcon";
import {ResponsiveTableContainer} from "~/components/subs/ResponsiveTableContainer.tsx";

export function meta({}: Route.MetaArgs) {
    return [
        { title: "Patients Management" },
        { name: "description", content: "Manage hospital patients" },
    ];
}

export default function Component() {
    const navigate = useNavigate();
    const [refreshingPatientList, setRefreshingPatientList] = useState<boolean>(false);
    const [patientInfo, setPatientInfo] = useState<{patients: PatientDataWithWardAndAdmission[], total_pages: number}>({patients: [], total_pages: 1});
    
    // Lists for filters
    const [teams, setTeams] = useState<DoctorTeamInfo[]>([]);
    const [wards, setWards] = useState<WardInfo[]>([]);
    const [loadingTeams, setLoadingTeams] = useState(false);
    const [loadingWards, setLoadingWards] = useState(false);

    const [sortKey, setSortKey] = useState<string>("");
    const [sortDesc, setSortDesc] = useState<boolean>(true);
    const [currPage, setCurrPage] = useState<number>(1);

    // Filter states
    const [nameSearch, setNameSearch] = useState<string>("");
    const [filterGenders, setFilterGenders] = useState<string[]>([]);
    const [filterHasTeam, setFilterHasTeam] = useState<number>(-1);
    const [filterIsAdmitted, setFilterIsAdmitted] = useState<number>(-1);
    const [filterTeams, setFilterTeams] = useState<number[]>([]);
    const [filterWards, setFilterWards] = useState<number[]>([]);

    const { changePage } = useOutletContext<OutletContextType>();

    useEffect(() => {
        refreshPatientList();
        loadTeamsList();
        loadWardsList();
    }, []);

    useEffect(() => {
        refreshPatientList();
    }, [currPage]);

    const loadTeamsList = () => {
        setLoadingTeams(true);
        apiGetTeamList(-1) // Get all teams
            .then(res => {
                if (res.success) {
                    setTeams(res.data.teams);
                } else {
                    showErrorMessage(res.message, "Failed to load teams");
                }
            })
            .catch(err => {})
            .finally(() => setLoadingTeams(false));
    };

    const loadWardsList = () => {
        setLoadingWards(true);
        apiGetWardList(-1, true) // Get all wards
            .then(res => {
                if (res.success) {
                    setWards(res.data.wards);
                } else {
                    showErrorMessage(res.message, "Failed to load wards");
                }
            })
            .catch(err => {})
            .finally(() => setLoadingWards(false));
    };

    const updateFilter = (
        name: string, 
        genders: string[], 
        hasTeam: string, 
        isAdmitted: string,
        teams: number[],
        wards: number[]
    ) => {
        setNameSearch(name);
        setFilterGenders(genders);
        setFilterHasTeam(Number(hasTeam));
        setFilterIsAdmitted(Number(isAdmitted));
        setFilterTeams(teams);
        setFilterWards(wards);
    };

    const refreshPatientList = () => {
        setRefreshingPatientList(true);
        apiGetPatientsList(currPage).then(res => {
            if (!res.success) {
                showErrorMessage(res.message, "Failed to get patient list");
                return;
            }
            setPatientInfo(res.data);
        })
        .catch(err => {})
        .finally(() => { setRefreshingPatientList(false); });
    };

    const handleSort = (key: string) => {
        if (sortKey === key) {
            setSortDesc(!sortDesc);
        } else {
            setSortKey(key);
            setSortDesc(false); // Default ascending
        }
    };

    const sortedPatients = useMemo<PatientDataWithWardAndAdmission[]>(() => {
        let data = [...patientInfo.patients];

        // Apply all filters
        data = data.filter((p) => {
            // Name search
            const matchesName = !nameSearch || (
                (p.name?.toLowerCase().includes(nameSearch.toLowerCase()) || 
                p.title?.toLowerCase().includes(nameSearch.toLowerCase()))
            );
            
            // Gender filter
            const okGender = filterGenders.length === 0 || filterGenders.includes(p.gender);
            
            // Team assignment status filter
            const okTeam = filterHasTeam === -1 || 
                (filterHasTeam === 1 ? p.admission?.team_id != null : p.admission?.team_id == null);
            
            // Admission status filter
            const okAdmitted = filterIsAdmitted === -1 || 
                (filterIsAdmitted === 1 ? p.admission != null : p.admission == null);
            
            // Specific teams filter
            const okSpecificTeams = filterTeams.length === 0 || 
                (p.admission?.team_id != null && filterTeams.includes(p.admission.team_id));
            
            // Specific wards filter
            const okSpecificWards = filterWards.length === 0 || 
                (p.ward?.id != null && filterWards.includes(p.ward.id));
            
            return matchesName && okGender && okTeam && okAdmitted && okSpecificTeams && okSpecificWards;
        });

        if (!sortKey) return data;

        data.sort((a, b) => {
            const valA = a[sortKey];
            const valB = b[sortKey];
            
            if (typeof valA === 'string' && typeof valB === 'string') {
                const cmp = valA.localeCompare(valB);
                return sortDesc ? -cmp : cmp;
            }

            if (typeof valA === 'number' && typeof valB === 'number') {
                return sortDesc ? valB - valA : valA - valB;
            }
            
            return 0;
        });
        
        return data;
    }, [
        patientInfo.patients, 
        sortKey, 
        sortDesc, 
        nameSearch,
        filterGenders, 
        filterHasTeam, 
        filterIsAdmitted,
        filterTeams,
        filterWards
    ]);

    // Convert teams and wards to options format for MultiSelect
    const teamOptions = useMemo(() => {
        return teams.map(team => ({
            value: team.id.toString(),
            label: team.department.replace(/_/g, ' ')
        }));
    }, [teams]);

    const wardOptions = useMemo(() => {
        return wards.map(ward => ({
            value: ward.id.toString(),
            label: `${ward.name} (${ward.current_occupancy}/${ward.total_capacity})`
        }));
    }, [wards]);

    const handleViewPatientInfo = (patient: PatientDataWithWardAndAdmission) => {
        modals.open({
            title: "Patient Information",
            centered: true,
            size: "md",
            children: (
                <Stack>
                    <Group>
                        <Text fw={500} w={100}>Name:</Text>
                        <Text>{`${patient.title} ${patient.name}`}</Text>
                    </Group>
                    <Group>
                        <Text fw={500} w={100}>Gender:</Text>
                        <Text>{patient.gender}</Text>
                    </Group>
                    <Group>
                        <Text fw={500} w={100}>Birth Date:</Text>
                        <Text>{patient.birth_date}</Text>
                    </Group>
                    <Group>
                        <Text fw={500} w={100}>Email:</Text>
                        <Text>{patient.email}</Text>
                    </Group>
                    <Group>
                        <Text fw={500} w={100}>Phone:</Text>
                        <Text>{patient.phone}</Text>
                    </Group>
                    <Group>
                        <Text fw={500} w={100}>Address:</Text>
                        <Text>{patient.address}</Text>
                    </Group>
                    <Group>
                        <Text fw={500} w={100}>Postcode:</Text>
                        <Text>{patient.postcode}</Text>
                    </Group>
                    
                    <Group justify="flex-end" mt="md">
                        <Button onClick={() => modals.closeAll()}>Close</Button>
                    </Group>
                </Stack>
            )
        });
    };

    const handleEditPatient = (patient: PatientDataWithWardAndAdmission) => {
        confirmEditPatient(patient, refreshPatientList);
    };

    const handleViewWard = (wardId: number) => {
        confirmCheckWardPatients(wardId, refreshPatientList);
    };

    const handlePatientDischarge = (admissionId: number, patientName: string) => {
        confirmPatientDischarge(admissionId, patientName, refreshPatientList);
    };

    const rows = sortedPatients.map((patient) => (
        <Table.Tr key={patient.id}>
            <Table.Td>{patient.id}</Table.Td>
            <Table.Td>
                <PatientInfoDisplay patientId={patient.id} />
            </Table.Td>
            <Table.Td>{patient.gender}</Table.Td>
            <Table.Td>{patient.birth_date}</Table.Td>
            <Table.Td>{patient.email}</Table.Td>
            <Table.Td>{patient.phone}</Table.Td>
            <Table.Td>
                {patient.admission?.team_id ? (
                    <TeamInfoDisplay teamId={patient.admission.team_id} />
                ) : (
                    <Text size="sm" c="dimmed">Not Assigned</Text>
                )}
            </Table.Td>
            <Table.Td>
                {patient.ward ? (
                    <Group gap="xs">
                        <Text>{patient.ward.name}</Text>
                        <ActionIcon 
                            size="sm"
                            onClick={() => handleViewWard(patient.ward!.id)}
                            title="View ward details"
                        >
                            <InfoIcon style={iconMStyle} />
                        </ActionIcon>
                    </Group>
                ) : (
                    <Text size="sm" c="dimmed">Not Admitted</Text>
                )}
            </Table.Td>
            <Table.Td>
                <Group>
                    <Tooltip label="Treatment Record" withArrow>
                        <ActionIcon onClick={() => { changePage(DashboardPageType.TreatmentRecord, `/dashboard/treatment_record/${patient.id}`) }}>
                            <HistoryIcon style={iconMStyle}/>
                        </ActionIcon>
                    </Tooltip>
                    <ActionIcon onClick={() => handleViewPatientInfo(patient)} title="View patient info">
                        <InfoIcon style={iconMStyle}/>
                    </ActionIcon>
                    <ActionIcon onClick={() => handleEditPatient(patient)} title="Edit patient info">
                        <PencilIcon style={iconMStyle}/>
                    </ActionIcon>
                    <Tooltip label="Reset Password" withArrow>
                        <ActionIcon onClick={() => { confirmResetPassword(patient.id, UserType.PATIENT) }}>
                            <LockResetIcon style={iconMStyle}/>
                        </ActionIcon>
                    </Tooltip>
                    <Tooltip label={patient.admission ? "Discharge patient" : "Not admitted"}>
                        <ActionIcon 
                            color="red" 
                            onClick={() => patient.admission && handlePatientDischarge(patient.admission.id, `${patient.title} ${patient.name}`)}
                            disabled={!patient.admission}
                            title="Discharge patient"
                        >
                            <LogoutVariantIcon style={iconMStyle}/>
                        </ActionIcon>
                    </Tooltip>
                </Group>
            </Table.Td>
        </Table.Tr>
    ));

    return (
        <Stack>
            <Group justify="space-between" align="center" style={marginLeftRight}>
                <Text size="1.5em" fw={700}>Patients Management</Text>
                <Button
                    leftSection={<AddIcon style={iconMStyle}/>}
                    onClick={() => { confirmAdminAddUser(0, refreshPatientList); }}
                >Add Patient</Button>
            </Group>

            <Card padding="lg" radius="md" withBorder style={marginTopBottom}>
                <Card.Section withBorder>
                    <Accordion variant="filled" chevronPosition="left" defaultValue="advanced-filter">
                        <Accordion.Item value="advanced-filter">
                            <Accordion.Control>
                                <Group>
                                    <FilterIcon style={iconMStyle} />
                                    <Text>Filters</Text>
                                </Group>
                            </Accordion.Control>
                            <Accordion.Panel>
                                <PatientManagementFilter 
                                    onChange={updateFilter}
                                    teamOptions={teamOptions}
                                    wardOptions={wardOptions}
                                />
                            </Accordion.Panel>
                        </Accordion.Item>
                    </Accordion>
                </Card.Section>

                <Card.Section>
                    <ResponsiveTableContainer minWidth={600}>
                        <Table striped highlightOnHover withColumnBorders withTableBorder>
                            <Table.Thead>
                                <Table.Tr>
                                    <Table.Th onClick={() => handleSort("id")}>
                                        Patient ID{" "}
                                        {sortKey === "id" && SORT_SYMBOLS[sortDesc ? "desc" : "asc"]}
                                    </Table.Th>
                                    <Table.Th onClick={() => handleSort("name")}>
                                        Name{" "}
                                        {sortKey === "name" && SORT_SYMBOLS[sortDesc ? "desc" : "asc"]}
                                    </Table.Th>
                                    <Table.Th onClick={() => handleSort("gender")}>
                                        Gender{" "}
                                        {sortKey === "gender" && SORT_SYMBOLS[sortDesc ? "desc" : "asc"]}
                                    </Table.Th>
                                    <Table.Th onClick={() => handleSort("birth_date")}>
                                        Birth Date{" "}
                                        {sortKey === "birth_date" && SORT_SYMBOLS[sortDesc ? "desc" : "asc"]}
                                    </Table.Th>
                                    <Table.Th onClick={() => handleSort("email")}>
                                        Email{" "}
                                        {sortKey === "email" && SORT_SYMBOLS[sortDesc ? "desc" : "asc"]}
                                    </Table.Th>
                                    <Table.Th onClick={() => handleSort("phone")}>
                                        Phone{" "}
                                        {sortKey === "phone" && SORT_SYMBOLS[sortDesc ? "desc" : "asc"]}
                                    </Table.Th>
                                    <Table.Th>
                                        Medical Team
                                    </Table.Th>
                                    <Table.Th>
                                        Ward
                                    </Table.Th>
                                    <Table.Th>
                                        Operations
                                    </Table.Th>
                                </Table.Tr>
                            </Table.Thead>
                            <Table.Tbody>{rows}</Table.Tbody>
                        </Table>
                    </ResponsiveTableContainer>

                    <Pagination 
                        withEdges 
                        total={patientInfo.total_pages} 
                        value={currPage} 
                        onChange={setCurrPage} 
                        mt="sm"
                        style={{justifyItems: "flex-end", ...marginRightBottom}}
                    />
                </Card.Section>
            </Card>
        </Stack>
    );
}
