import { IconSpan } from './icon-span';
import { departmentIcon } from './icons';
import type { BookingPrefill, ChatToolPart, ToolOutputs } from './types';

type WidgetProps = {
    part: ChatToolPart;
    onDepartmentClick: (department: string) => void;
    onShowDoctorSlots: (doctorName: string) => void;
    onSuggestBooking: () => void;
    onPickSlot: (prefill: BookingPrefill) => void;
    onPickBranch: (branch: string) => void;
};

// Dispatcher — renders the right widget for a tool part based on its name and state.
export const ChatToolWidget = ({
    part,
    onDepartmentClick,
    onShowDoctorSlots,
    onSuggestBooking,
    onPickSlot,
    onPickBranch,
}: WidgetProps) => {
    if (part.state === 'input-streaming' || part.state === 'input-available') {
        return <ToolLoadingRow toolName={part.toolName} />;
    }
    if (part.state === 'output-error') {
        return <div class="chat-widget-error">Couldn't load: {part.errorText ?? 'unknown error'}</div>;
    }

    switch (part.toolName) {
        case 'pick_branch': {
            const out = part.output as ToolOutputs['pick_branch'] | undefined;
            if (!out?.branches?.length) return null;
            return <BranchPickerWidget branches={out.branches} onPick={onPickBranch} />;
        }
        case 'list_departments': {
            const out = part.output as ToolOutputs['list_departments'] | undefined;
            if (!out?.departments?.length) return null;
            return <DepartmentListWidget departments={out.departments} onPick={onDepartmentClick} />;
        }
        case 'show_clinic_timings': {
            const out = part.output as ToolOutputs['show_clinic_timings'] | undefined;
            if (!out?.departments?.length) return null;
            return <ClinicTimingsWidget departments={out.departments} />;
        }
        case 'show_doctors': {
            const out = part.output as ToolOutputs['show_doctors'] | undefined;
            if (!out?.doctors?.length) {
                return (
                    <div class="chat-widget-empty">
                        No doctors found in {out?.department ?? 'this department'}.
                    </div>
                );
            }
            return (
                <DoctorsListWidget
                    department={out.department}
                    doctors={out.doctors}
                    onPickDoctor={onShowDoctorSlots}
                />
            );
        }
        case 'show_doctor_slots': {
            const out = part.output as ToolOutputs['show_doctor_slots'] | undefined;
            if (!out) return null;
            if (out.error || !out.doctor) {
                return <div class="chat-widget-empty">{out.error ?? 'Doctor not found.'}</div>;
            }
            return <DoctorSlotsWidget data={out} onPickSlot={onPickSlot} />;
        }
        case 'suggest_booking': {
            const out = part.output as ToolOutputs['suggest_booking'] | undefined;
            return (
                <BookingSuggestionWidget
                    reason={out?.reason ?? 'Book an appointment.'}
                    department={out?.department ?? null}
                    onBook={onSuggestBooking}
                />
            );
        }
        default:
            return null;
    }
};

const TOOL_LABELS: Record<string, string> = {
    pick_branch: 'Fetching branches…',
    list_departments: 'Looking up departments…',
    show_clinic_timings: 'Fetching clinic hours…',
    show_doctors: 'Looking up doctors…',
    show_doctor_slots: 'Checking availability…',
    suggest_booking: 'Thinking about booking options…',
};

const ToolLoadingRow = ({ toolName }: { toolName: string }) => (
    <div class="chat-widget-loading">
        <span class="chat-typing-dots" aria-hidden="true">
            <span /><span /><span />
        </span>
        <span class="chat-widget-loading-label">{TOOL_LABELS[toolName] ?? 'Working…'}</span>
    </div>
);

type BranchPickerProps = {
    branches: ToolOutputs['pick_branch']['branches'];
    onPick: (branch: string) => void;
};

const BranchPickerWidget = ({ branches, onPick }: BranchPickerProps) => (
    <div class="chat-widget chat-widget-branches">
        <div class="chat-widget-title">Which branch?</div>
        {branches.map(b => (
            <button key={b.name} class="chat-widget-branch-card" onClick={() => onPick(b.name)}>
                <div class="chat-widget-branch-name">{b.name}</div>
                <div class="chat-widget-branch-meta">
                    {b.doctorCount} {b.doctorCount === 1 ? 'doctor' : 'doctors'}
                    {b.departmentCount > 0 ? ` • ${b.departmentCount} ${b.departmentCount === 1 ? 'department' : 'departments'}` : ''}
                </div>
            </button>
        ))}
    </div>
);

type DepartmentListProps = {
    departments: string[];
    onPick: (department: string) => void;
};

const DepartmentListWidget = ({ departments, onPick }: DepartmentListProps) => (
    <div class="chat-widget chat-widget-departments">
        <div class="chat-widget-title">Departments</div>
        <div class="chat-widget-dept-grid">
            {departments.map(dept => (
                <button
                    key={dept}
                    class="chat-widget-dept-chip"
                    onClick={() => onPick(dept)}
                    title={`Show doctors in ${dept}`}
                >
                    <IconSpan name={departmentIcon(dept)} size={16} />
                    <span>{dept}</span>
                </button>
            ))}
        </div>
    </div>
);

type ClinicTimingsProps = {
    departments: ToolOutputs['show_clinic_timings']['departments'];
};

const ClinicTimingsWidget = ({ departments }: ClinicTimingsProps) => (
    <div class="chat-widget chat-widget-timings">
        <div class="chat-widget-title">
            <IconSpan name="calendar" size={14} /> Clinic hours
        </div>
        {departments.map(dept => (
            <div key={dept.name} class="chat-widget-timing-dept">
                <div class="chat-widget-timing-dept-name">
                    <IconSpan name={departmentIcon(dept.name)} size={14} />
                    <span>{dept.name}</span>
                </div>
                {dept.entries.map(entry => (
                    <div key={`${dept.name}-${entry.name}`} class="chat-widget-timing-row">
                        <div class="chat-widget-timing-doctor">{entry.name}</div>
                        <div class="chat-widget-timing-hours">{entry.hours}</div>
                        {entry.clinic && (
                            <div class="chat-widget-timing-clinic">{entry.clinic}</div>
                        )}
                    </div>
                ))}
            </div>
        ))}
    </div>
);

type DoctorsListProps = {
    department: string;
    doctors: ToolOutputs['show_doctors']['doctors'];
    onPickDoctor: (doctorName: string) => void;
};

const DoctorsListWidget = ({ department, doctors, onPickDoctor }: DoctorsListProps) => (
    <div class="chat-widget chat-widget-doctors">
        <div class="chat-widget-title">
            <IconSpan name={departmentIcon(department)} size={14} /> {department}
        </div>
        {doctors.map(doc => (
            <div key={doc.id} class="chat-widget-doctor-card">
                <div class="chat-widget-doctor-name">{doc.name}</div>
                {doc.specialty && <div class="chat-widget-doctor-meta">{doc.specialty}</div>}
                {doc.visitingHours && <div class="chat-widget-doctor-meta">{doc.visitingHours}</div>}
                {doc.clinic && <div class="chat-widget-doctor-meta">{doc.clinic}</div>}
                <button
                    class="chat-widget-doctor-action"
                    onClick={() => onPickDoctor(doc.name)}
                >
                    <IconSpan name="calendar" size={12} /> See available appointments
                </button>
            </div>
        ))}
    </div>
);

type DoctorSlotsProps = {
    data: ToolOutputs['show_doctor_slots'];
    onPickSlot: (prefill: BookingPrefill) => void;
};

const DoctorSlotsWidget = ({ data, onPickSlot }: DoctorSlotsProps) => {
    if (!data.doctor) return null;
    const doctor = data.doctor;
    const available = data.slots.filter(s => s.available);
    const hasAny = available.length > 0;

    return (
        <div class="chat-widget chat-widget-slots">
            <div class="chat-widget-title">
                <IconSpan name="calendar" size={14} /> Available slots
            </div>
            <div class="chat-widget-slots-doctor">{doctor.name}</div>
            <div class="chat-widget-slots-meta">
                {formatDate(data.date)}
                {doctor.clinic ? ` • ${doctor.clinic}` : ''}
            </div>
            {hasAny ? (
                <div class="chat-widget-slots-grid">
                    {data.slots.map(s => (
                        <button
                            key={s.time}
                            class={`chat-widget-slot-btn ${s.available ? '' : 'unavailable'}`}
                            disabled={!s.available}
                            onClick={() =>
                                s.available &&
                                onPickSlot({ doctorId: doctor.id, date: data.date, time: s.time })
                            }
                        >
                            {s.time}
                        </button>
                    ))}
                </div>
            ) : (
                <div class="chat-widget-empty">No slots available on this date.</div>
            )}
        </div>
    );
};

const formatDate = (iso: string): string => {
    // iso is YYYY-MM-DD from the backend. Render as e.g. "Mon, 6 Apr".
    const d = new Date(iso + 'T00:00:00');
    if (isNaN(d.getTime())) return iso;
    return d.toLocaleDateString(undefined, { weekday: 'short', day: 'numeric', month: 'short' });
};

type BookingSuggestionProps = {
    reason: string;
    department: string | null;
    onBook: () => void;
};

const BookingSuggestionWidget = ({ reason, department, onBook }: BookingSuggestionProps) => (
    <div class="chat-widget chat-widget-booking">
        <div class="chat-widget-booking-icon">
            <IconSpan name="calendar" size={28} />
        </div>
        <div class="chat-widget-booking-body">
            <div class="chat-widget-booking-title">Book an appointment</div>
            <div class="chat-widget-booking-reason">{reason}</div>
            {department && <div class="chat-widget-booking-dept">Suggested: {department}</div>}
            <button class="widget-btn" onClick={onBook}>Book now</button>
        </div>
    </div>
);
