import type {Route} from "../../../.react-router/types/app/pages/dashboard/+types/DoctorTreatment";
import {useEffect, useMemo, useState} from "react";
import {BookingCategory, UserPermissionLevel} from "~/utils/hms_enums.ts";
import {useNavigate, useOutletContext} from "react-router";
import {
    type DoctorTeamInfo,
    type OutletContextType,
    type PatientBookingInfoWithAdmission,
    SORT_SYMBOLS,
    WardTypes
} from "~/utils/models.ts";
import {Accordion, ActionIcon, Badge, Button, Card, Group, Modal, Select, Stack, Table, Text, Textarea} from "@mantine/core";
import {apiDoctorTreat, apiGetDoctorAppointments, apiGetTeamList, apiGetWardList} from "~/utils/hms_api.ts";
import {showErrorMessage, showInfoMessage} from "~/utils/utils.ts";
import {iconMStyle, marginLeftRight, marginTopBottom} from "~/styles.ts";
import {confirmCheckWardPatients} from "~/components/subs/confirms.tsx";
import {TruncatedText} from "~/components/subs/TruncatedText.tsx";
import InfoIcon from "mdi-react/InfoIcon";
import NoteEditIcon from "mdi-react/NoteEditIcon";
import {useForm} from "@mantine/form";
import {PatientInfoDisplay} from "~/components/subs/PatientInfoDisplay.tsx";
import FilterIcon from "mdi-react/FilterIcon";
import {ResponsiveTableContainer} from "~/components/subs/ResponsiveTableContainer.tsx";
import {TeamInfoDisplay} from "~/components/subs/TeamInfoDisplay.tsx";

export function meta({}: Route.MetaArgs) {
    return [
        { title: "Doctor Treatment" },
        { name: "description", content: "Record treatment information for patients" },
    ];
}

function TreatmentModal({ 
    opened, 
    onClose, 
    appointmentId, 
    patientName,
    patientId,
    onSuccess
}: { 
    opened: boolean; 
    onClose: () => void; 
    appointmentId: number;
    patientName: string;
    patientId: number;
    onSuccess: () => void;
}) {
    const [loading, setLoading] = useState(false);
    
    const form = useForm({
        initialValues: {
            treatment_info: ''
        },
        validate: {
            treatment_info: (value) => (!value ? 'Treatment information is required' : null)
        }
    });
    
    const handleSubmit = (values: typeof form.values) => {
        setLoading(true);
        // Current timestamp in seconds
        const currentTime = Math.floor(Date.now() / 1000);
        
        apiDoctorTreat(
            appointmentId,
            values.treatment_info,
            currentTime
        ).then(res => {
            if (res.success) {
                showInfoMessage("Treatment record saved successfully", "Success");
                onSuccess();
                onClose();
            } else {
                showErrorMessage(res.message, "Failed to save treatment record");
            }
        })
        .catch(err => {
            showErrorMessage("Failed to save treatment record", "Error");
        })
        .finally(() => {
            setLoading(false);
        });
    };
    
    return (
        <Modal 
            opened={opened} 
            onClose={onClose} 
            title="Record Treatment"
            size="lg"
            centered
        >
            <Stack gap="md">
                <Group>
                    <Text fw={500}>Patient:</Text>
                    <PatientInfoDisplay patientId={patientId} showIcon={false} />
                </Group>
                
                <form onSubmit={form.onSubmit(handleSubmit)}>
                    <Stack gap="md">
                        <Textarea
                            label="Treatment Information"
                            description="Please provide detailed information about the treatment provided"
                            placeholder="Enter treatment details, medications, observations, etc."
                            required
                            minRows={5}
                            maxRows={10}
                            {...form.getInputProps('treatment_info')}
                        />
                        
                        <Group justify="flex-end" mt="md">
                            <Button variant="outline" onClick={onClose}>Cancel</Button>
                            <Button type="submit" loading={loading}>Save Treatment Record</Button>
                        </Group>
                    </Stack>
                </form>
            </Stack>
        </Modal>
    );
}

export default function Component() {
    const navigate = useNavigate();
    const [loading, setLoading] = useState(true);
    const [appointments, setAppointments] = useState<PatientBookingInfoWithAdmission[]>([]);
    const [wardMap, setWardMap] = useState<Map<number, string>>(new Map());
    
    // Treatment modal state
    const [treatmentModalOpen, setTreatmentModalOpen] = useState(false);
    const [selectedAppointment, setSelectedAppointment] = useState<PatientBookingInfoWithAdmission | null>(null);
    
    const [sortKey, setSortKey] = useState<string>("appointment_time");
    const [sortDesc, setSortDesc] = useState<boolean>(true);

    const [selectedTeamId, setSelectedTeamId] = useState<string | null>(null);
    const [teamList, setTeamList] = useState<DoctorTeamInfo[]>([]);

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

    useEffect(() => {
        fetchAppointments();
        fetchWards();
        refreshTeamList()
    }, []);

    const refreshTeamList = () => {
        apiGetTeamList(-1).then(res => {
            if (res.success) {
                setTeamList(res.data.teams)
            }
            else {
                showErrorMessage(res.message, "Failed to fetch teams");
            }
        }).catch(err => showErrorMessage(err.toString(), "Failed to fetch teams"));
    }

    const getMemberNameFromTeam = (team: DoctorTeamInfo, doctorId: number) => {
        const member = team.members.find(member => member.id === doctorId);
        return member ? `${member.title} ${member.name}`.trim() : `Doctor ID: ${doctorId}`;
    }
    
    const fetchAppointments = (target_team_id?: number) => {
        setLoading(true);
        apiGetDoctorAppointments(target_team_id)
            .then(res => {
                if (res.success) {
                    setAppointments(res.data.appointments);
                } else {
                    showErrorMessage(res.message, "Failed to fetch appointments");
                }
            })
            .catch(err => {
                showErrorMessage("Failed to fetch appointments", "Error");
            })
            .finally(() => {
                setLoading(false);
            });
    };
    
    const fetchWards = () => {
        apiGetWardList(1, true)
            .then(res => {
                if (res.success) {
                    const wardNameMap = new Map<number, string>();
                    res.data.wards.forEach(ward => {
                        wardNameMap.set(ward.id, `${ward.name} (${WardTypes[ward.type]})`);
                    });
                    setWardMap(wardNameMap);
                }
            })
            .catch(err => {
                showErrorMessage("Failed to fetch wards information", "Error");
            });
    };
    
    const handleSort = (key: string) => {
        if (sortKey === key) {
            setSortDesc(!sortDesc);
        } else {
            setSortKey(key);
            setSortDesc(false); // Default ascending
        }
    };

    const openTreatmentModal = (appointment: PatientBookingInfoWithAdmission) => {
        setSelectedAppointment(appointment);
        setTreatmentModalOpen(true);
    };
    
    const closeTreatmentModal = () => {
        setTreatmentModalOpen(false);
        setSelectedAppointment(null);
    };
    
    const handleViewWard = (wardId: number) => {
        confirmCheckWardPatients(wardId, fetchAppointments);
    };
    
    const getCategoryDisplay = (category: string) => {
        const key = Object.entries(BookingCategory).find(([_, value]) => value === category)?.[0];
        return key ? key.replace(/_/g, ' ') : category;
    };
    
    const getStatusBadge = (appointment: PatientBookingInfoWithAdmission) => {
        if (appointment.discharged) {
            return <Badge color="purple">Discharged</Badge>;
        } else if (appointment.admitted) {
            return <Badge color="blue">Admitted</Badge>;
        } else {
            return <Badge color="yellow">Pending</Badge>;
        }
    };
    
    const sortedAppointments = useMemo(() => {
        let data = [...appointments];
        
        // Apply sorting
        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;
    }, [appointments, sortKey, sortDesc]);
    
    const rows = sortedAppointments.map((appointment) => (
        <Table.Tr key={appointment.id}>
            <Table.Td>{appointment.id}</Table.Td>
            <Table.Td>
                <PatientInfoDisplay patientId={appointment.patient_id} />
            </Table.Td>
            <Table.Td>{getCategoryDisplay(appointment.category)}</Table.Td>
            <Table.Td>{new Date(appointment.appointment_time * 1000).toLocaleString('en-GB').replace(',', '')}</Table.Td>
            <Table.Td>
                <TruncatedText 
                    text={appointment.description} 
                    title={`Description - Appointment #${appointment.id}`}
                />
            </Table.Td>
            <Table.Td>{getStatusBadge(appointment)}</Table.Td>
            <Table.Td>
                <Group gap="xs">
                    <Text>{wardMap.get(appointment.admission.ward_id) || `Ward ID: ${appointment.admission.ward_id}`}</Text>
                    <ActionIcon 
                        size="sm"
                        onClick={() => handleViewWard(appointment.admission.ward_id)}
                        title="View ward details"
                    >
                        <InfoIcon style={iconMStyle} />
                    </ActionIcon>
                </Group>
            </Table.Td>
            <Table.Td>
                <TeamInfoDisplay teamId={appointment.assigned_team || -1} />
            </Table.Td>
            <Table.Td>
                <Group>
                    <ActionIcon 
                        color="blue" 
                        onClick={() => openTreatmentModal(appointment)}
                        title="Record treatment"
                    >
                        <NoteEditIcon style={iconMStyle}/>
                    </ActionIcon>
                </Group>
            </Table.Td>
        </Table.Tr>
    ));

    const handleTeamChange = (value: string | null) => {
        setSelectedTeamId(value);
        const teamId = value === null ? undefined : parseInt(value);
        fetchAppointments(teamId);
    };

    return (
        <Stack>
            <Group justify="space-between" align="center" style={marginLeftRight}>
                <Text size="1.5em" fw={700}>Patient Treatment</Text>
                <Button
                    onClick={() => fetchAppointments(selectedTeamId ? parseInt(selectedTeamId) : undefined)}
                    loading={loading}
                    variant="outline"
                >Refresh</Button>
            </Group>

            <Card padding="lg" radius="md" withBorder style={marginTopBottom}>
                { loginUserInfo && loginUserInfo.user_permission >= UserPermissionLevel.ADMIN &&
                    <Card.Section withBorder>
                        <Accordion variant="filled" chevronPosition="left" defaultValue="advanced-filter">
                            <Accordion.Item value="advanced-filter">
                                <Accordion.Control>
                                    <Group>
                                        <Text>Select a Team</Text>
                                    </Group>
                                </Accordion.Control>
                                <Accordion.Panel>
                                    <Group grow>
                                        <Select
                                            label="Select Team"
                                            placeholder="Select a medical team"
                                            data={[
                                                { value: "-1", label: "All Teams" },
                                                ...(teamList.map(team => ({
                                                    value: team.id.toString(),
                                                    label: `Team ${team.id}: ${team.department.replace(/_/g, ' ')} (${getMemberNameFromTeam(team, team.consultant_id)})`
                                                })) || [])
                                            ]}
                                            value={selectedTeamId}
                                            onChange={handleTeamChange}
                                            searchable
                                            clearable
                                        />
                                    </Group>
                                </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")}>
                                        ID{" "}
                                        {sortKey === "id" && SORT_SYMBOLS[sortDesc ? "desc" : "asc"]}
                                    </Table.Th>
                                    <Table.Th onClick={() => handleSort("patient_id")}>
                                        Patient{" "}
                                        {sortKey === "patient_id" && SORT_SYMBOLS[sortDesc ? "desc" : "asc"]}
                                    </Table.Th>
                                    <Table.Th onClick={() => handleSort("category")}>
                                        Category{" "}
                                        {sortKey === "category" && SORT_SYMBOLS[sortDesc ? "desc" : "asc"]}
                                    </Table.Th>
                                    <Table.Th onClick={() => handleSort("appointment_time")}>
                                        Appointment Time{" "}
                                        {sortKey === "appointment_time" && SORT_SYMBOLS[sortDesc ? "desc" : "asc"]}
                                    </Table.Th>
                                    <Table.Th>
                                        Description
                                    </Table.Th>
                                    <Table.Th onClick={() => handleSort("admitted")}>
                                        Status{" "}
                                        {sortKey === "admitted" && SORT_SYMBOLS[sortDesc ? "desc" : "asc"]}
                                    </Table.Th>
                                    <Table.Th>
                                        Ward
                                    </Table.Th>
                                    <Table.Th>
                                        Medical Team
                                    </Table.Th>
                                    <Table.Th>
                                        Actions
                                    </Table.Th>
                                </Table.Tr>
                            </Table.Thead>
                            <Table.Tbody>{rows}</Table.Tbody>
                        </Table>
                    </ResponsiveTableContainer>
                </Card.Section>
            </Card>
            
            {selectedAppointment && (
                <TreatmentModal
                    opened={treatmentModalOpen}
                    onClose={closeTreatmentModal}
                    appointmentId={selectedAppointment.id}
                    patientName={`Patient ID: ${selectedAppointment.patient_id}`}
                    patientId={selectedAppointment.patient_id}
                    onSuccess={fetchAppointments}
                />
            )}
        </Stack>
    );
}
