import React, { useMemo, useState } from 'react';
import { useErrorToast } from '@nexuscrm/salesforce-crm-standard-frontend/platform/components/ui';
import { DndContext, DragOverlay, useDraggable, useDroppable, DragEndEvent, DragStartEvent } from '@dnd-kit/core';
import { Loader2 } from 'lucide-react';
import { SObjectDescribe, SObject } from '../../types';
import { COMMON_FIELDS } from '../../core/constants';
import { isSystemField } from '../../core/constants/CommonFields';
import { Logger } from '../../core/services/Logger';
import { supportsStatusFieldPresentation } from '../../core/utils/statusFieldPresentation';

interface KanbanBoardProps {
    objectMetadata: SObjectDescribe;
    records: SObject[];
    groupByField?: string;
    onRecordClick?: (record: SObject) => void;
    onUpdateRecord?: (recordId: string, updates: Record<string, unknown>) => Promise<void>;
    loading?: boolean;
}

export const KanbanBoard: React.FC<KanbanBoardProps> = ({
    objectMetadata,
    records,
    groupByField: propGroupBy,
    onRecordClick,
    onUpdateRecord,
    loading
}) => {
    const errorToast = useErrorToast();
    const [activeId, setActiveId] = useState<string | null>(null);

    // Determine Group By Field
    const groupByField = useMemo(() => {
        if (propGroupBy) return propGroupBy;
        if (objectMetadata.kanbanGroupBy) return objectMetadata.kanbanGroupBy;

        // Fallback: Check for 'stage_name' (standard for Opps) or default to 'status'
        const hasStage = objectMetadata.fields?.some(f => f.name === 'stage_name');
        return hasStage ? 'stage_name' : COMMON_FIELDS.STATUS;
    }, [propGroupBy, objectMetadata]);

    // Get Columns
    const { columns, groupedRecords } = useMemo(() => {
        const fieldMeta = objectMetadata.fields?.find(f => f.name === groupByField);

        let cols: string[] = [];
        // Fix invalid TS type check for status fields
        if (supportsStatusFieldPresentation(fieldMeta?.type) && fieldMeta?.picklistValues && fieldMeta.picklistValues.length > 0) {
            cols = fieldMeta.picklistValues.map(v => v.value);
        } else {
            // Fallback: derived from data
            const values = new Set(records.map(r => String(r[groupByField] || 'Unassigned')));
            cols = Array.from(values).sort();
        }

        const groups: Record<string, SObject[]> = {};
        cols.forEach(c => groups[c] = []);

        records.forEach(r => {
            const val = String(r[groupByField] || 'Unassigned');
            if (!groups[val]) {
                // Handle values outside defined columns (add dynamically if needed, or skip/bucket)
                if (!groups[val]) groups[val] = []; // Dynamically add if missing from options
                if (!cols.includes(val)) cols.push(val);
            }
            groups[val].push(r);
        });

        return { columns: cols, groupedRecords: groups };
    }, [objectMetadata, records, groupByField]);

    // Handlers
    const handleDragStart = (event: DragStartEvent) => {
        setActiveId(event.active.id as string);
    };

    const handleDragEnd = async (event: DragEndEvent) => {
        const { active, over } = event;
        setActiveId(null);

        if (!over) return;

        const recordId = active.id as string;
        const newStatus = over.id as string;

        // Find record
        const record = records.find(r => (r[COMMON_FIELDS.ID] as string) === recordId);
        if (!record) return;

        const currentStatus = String(record[groupByField] || 'Unassigned');

        if (currentStatus !== newStatus) {
            // Optimistic update? Or loading state?
            // For now, call callback
            if (onUpdateRecord) {
                try {
                    await onUpdateRecord(recordId, { [groupByField]: newStatus });
                } catch (err: unknown) {
                    Logger.error('[KanbanBoard] Failed to update status', {}, err);
                    errorToast("Failed to update status");
                }
            }
        }
    };

    if (loading) {
        return (
            <div className="flex h-96 items-center justify-center text-slate-400">
                <Loader2 className="animate-spin mr-2" /> Loading Board...
            </div>
        );
    }

    const activeRecord = activeId ? records.find(r => (r[COMMON_FIELDS.ID] as string) === activeId) : null;

    return (
        <DndContext onDragStart={handleDragStart} onDragEnd={handleDragEnd}>
            <div className="flex h-full gap-4 overflow-x-auto pb-4 p-1">
                {columns.map(col => (
                    <KanbanColumn
                        key={col}
                        id={col}
                        title={col}
                        records={groupedRecords[col] || []}
                        objectMetadata={objectMetadata}
                        onRecordClick={onRecordClick}
                    />
                ))}
            </div>
            <DragOverlay>
                {activeRecord ? (
                    <KanbanCard
                        record={activeRecord}
                        objectMetadata={objectMetadata}
                        isOverlay
                    />
                ) : null}
            </DragOverlay>
        </DndContext>
    );
};

interface KanbanColumnProps {
    id: string;
    title: string;
    records: SObject[];
    objectMetadata: SObjectDescribe;
    onRecordClick?: (record: SObject) => void;
}

const KanbanColumn: React.FC<KanbanColumnProps> = ({ id, title, records, objectMetadata, onRecordClick }) => {
    const { setNodeRef } = useDroppable({
        id: id,
    });

    return (
        <div ref={setNodeRef} className="w-72 flex-shrink-0 flex flex-col bg-slate-50/50 rounded-xl border border-slate-200/60 max-h-[calc(100vh-250px)]">
            {/* Header */}
            <div className="p-3 border-b border-slate-200/60 flex justify-between items-center sticky top-0 bg-slate-50/90 backdrop-blur rounded-t-xl z-10">
                <h3 className="font-semibold text-slate-700 truncate">{title}</h3>
                <span className="bg-slate-200 text-slate-600 text-xs px-2 py-0.5 rounded-full font-mono">
                    {records.length}
                </span>
            </div>

            {/* Cards Container */}
            <div className="p-2 flex-1 overflow-y-auto space-y-2 min-h-[100px]">
                {records.map(record => (
                    <DraggableKanbanCard
                        key={record[COMMON_FIELDS.ID] as string}
                        record={record}
                        objectMetadata={objectMetadata}
                        onClick={() => onRecordClick && onRecordClick(record)}
                    />
                ))}
                {records.length === 0 && (
                    <div className="h-20 border-2 border-dashed border-slate-200 rounded-lg flex items-center justify-center text-slate-400 text-xs italic">
                        Drop items here
                    </div>
                )}
            </div>
        </div>
    );
};

interface KanbanCardProps {
    record: SObject;
    objectMetadata: SObjectDescribe;
    onClick?: () => void;
    isOverlay?: boolean;
}

const KanbanCard: React.FC<KanbanCardProps> = ({ record, objectMetadata, onClick, isOverlay }) => {
    const nameField = objectMetadata.fields?.find(f => f.nameField)?.name || COMMON_FIELDS.NAME;

    // Use kanbanSummaryField if available, otherwise find secondary fields to show
    const kanbanSummaryFieldValue = objectMetadata.kanbanSummaryField && record[objectMetadata.kanbanSummaryField]
        ? record[objectMetadata.kanbanSummaryField]
        : null;

    // Find some secondary fields to show (e.g. priority, type, owner)
    // Priority 1: Priority
    // Priority 2: Type
    // Priority 3: CreatedDate
    const secondaryFields = (objectMetadata.fields || [])
        .filter(f => !isSystemField(f.name) && f.name !== nameField && f.type !== 'richtextarea')
        .slice(0, 3);

    return (
        <div
            onClick={onClick}
            className={`
                bg-white p-3 rounded-lg border shadow-sm
                ${isOverlay ? 'shadow-xl rotate-2 scale-105 border-blue-400 cursor-grabbing' : 'border-slate-200 hover:shadow-md hover:border-blue-300 cursor-grab'}
                transition-all group relative select-none
            `}
        >
            <div className="font-medium text-slate-800 mb-2 truncate pr-6">
                {(record[nameField] as string) || 'Untitled'}
            </div>

            <div className="space-y-1">
                {secondaryFields.map(f => {
                    const val = record[f.name];
                    if (!val) return null;
                    return (
                        <div key={f.name} className="flex justify-between text-xs">
                            <span className="text-slate-400">{f.label}</span>
                            <span className="text-slate-600 font-medium truncate max-w-[120px]">{String(val)}</span>
                        </div>
                    )
                })}
            </div>

            <div className="mt-3 pt-2 border-t border-slate-50 flex justify-between items-center">
                {kanbanSummaryFieldValue ? (
                    <span className="text-[10px] text-slate-400 font-mono truncate max-w-[100px]" title={String(kanbanSummaryFieldValue)}>{String(kanbanSummaryFieldValue)}</span>
                ) : (
                    <span className="text-[10px] text-slate-400 font-mono">{(record[COMMON_FIELDS.ID] as string).substring(0, 6)}</span>
                )}
                {/* Avatar placeholder? */}
            </div>
        </div>
    );
};

const DraggableKanbanCard: React.FC<KanbanCardProps & { record: SObject }> = (props) => {
    const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
        id: props.record[COMMON_FIELDS.ID] as string,
    });

    if (isDragging) {
        return (
            <div
                ref={setNodeRef}
                className="bg-slate-50 border-2 border-dashed border-slate-200 rounded-lg h-24 opacity-50"
            />
        );
    }

    return (
        <div ref={setNodeRef} {...listeners} {...attributes}>
            <KanbanCard {...props} />
        </div>
    );
}
