'use client'

import { useEffect, useMemo, useState } from 'react'
import { fetchLeadDetail } from '@/lib/leads/api'
import type { AppUser, LeadDetailResponse, LeadPipelineStatus, LeadRecord, OutreachConfig, TeamUserRecord } from '@/lib/types'
import { canAccessLeadBackup } from '@/lib/auth/roles'
import LeadBackupPanel from '@/components/leads/LeadBackupPanel'
import ManualLeadForm from '@/components/leads/ManualLeadForm'
import LeadCRMPanel from './LeadCRMPanel'

interface LeadLibraryViewProps {
  leads: LeadRecord[]
  teamUsers: TeamUserRecord[]
  currentUser: AppUser
  outreachConfig: OutreachConfig
  onLeadUpdated: (lead: LeadRecord) => void
  onLibraryReload: () => Promise<void> | void
}

type SortKey = 'updated_at' | 'business_name' | 'status' | 'owner_display_name' | 'assigned_to_display_name' | 'next_follow_up_at'
type FollowUpFilter = 'all' | 'due'

const STAGE_LABELS: Record<LeadPipelineStatus, string> = {
  discovered: 'Discovered',
  saved: 'Saved',
  contacted: 'Contacted',
  in_discussion: 'In Discussion',
  negotiating: 'Negotiating',
  mou_signed: 'MOU Signed',
  converted: 'Converted',
  lost: 'Lost',
}

const STAGE_STYLES: Record<LeadPipelineStatus, string> = {
  discovered: 'bg-slate-500/10 text-slate-300 border border-slate-500/20',
  saved: 'bg-[#ffb95f]/10 text-[#ffb95f] border border-[#ffb95f]/20',
  contacted: 'bg-[#60a5fa]/10 text-[#60a5fa] border border-[#60a5fa]/20',
  in_discussion: 'bg-[#ac8aff]/10 text-[#ac8aff] border border-[#ac8aff]/20',
  negotiating: 'bg-[#f97316]/10 text-[#f97316] border border-[#f97316]/20',
  mou_signed: 'bg-[#22c55e]/10 text-[#22c55e] border border-[#22c55e]/20',
  converted: 'bg-[#14b8a6]/10 text-[#14b8a6] border border-[#14b8a6]/20',
  lost: 'bg-[#ef4444]/10 text-[#ef4444] border border-[#ef4444]/20',
}

function formatDateShort(value: string | null): string {
  if (!value) return 'None'

  return new Intl.DateTimeFormat('en', {
    dateStyle: 'medium',
  }).format(new Date(value))
}

function getFollowUpDueCount(leads: LeadRecord[]): number {
  const now = Date.now()
  return leads.filter(lead => lead.next_follow_up_at && new Date(lead.next_follow_up_at).getTime() <= now).length
}

function getOutreachStatus(lead: LeadRecord): { label: string; style: string } {
  const now = Date.now()

  if (lead.next_follow_up_at && new Date(lead.next_follow_up_at).getTime() <= now) {
    return {
      label: 'Follow-up due',
      style: 'bg-[#ef4444]/10 text-[#fca5a5] border border-[#ef4444]/20',
    }
  }

  if (lead.last_contact_at) {
    return {
      label: 'Active',
      style: 'bg-[#60a5fa]/10 text-[#93c5fd] border border-[#60a5fa]/20',
    }
  }

  return {
    label: 'Not contacted',
    style: 'bg-[#ffb95f]/10 text-[#ffd59a] border border-[#ffb95f]/20',
  }
}

function formatLastContact(value: string | null): string {
  if (!value) return 'Not contacted yet'

  const days = Math.max(0, Math.floor((Date.now() - new Date(value).getTime()) / 86_400_000))
  if (days === 0) return 'Last contacted today'
  if (days === 1) return 'Last contacted 1 day ago'
  return `Last contacted ${days} days ago`
}

export default function LeadLibraryView({
  leads,
  teamUsers,
  currentUser,
  outreachConfig,
  onLeadUpdated,
  onLibraryReload,
}: LeadLibraryViewProps) {
  const [search, setSearch] = useState('')
  const [stageFilter, setStageFilter] = useState<LeadPipelineStatus | 'all'>('all')
  const [ownerFilter, setOwnerFilter] = useState('all')
  const [assigneeFilter, setAssigneeFilter] = useState('all')
  const [followUpFilter, setFollowUpFilter] = useState<FollowUpFilter>('all')
  const [sortKey, setSortKey] = useState<SortKey>('updated_at')
  const [sortDir, setSortDir] = useState<'asc' | 'desc'>('desc')
  const [showManualForm, setShowManualForm] = useState(false)
  const [showBackupPanel, setShowBackupPanel] = useState(false)
  const [libraryMessage, setLibraryMessage] = useState('')
  const [selectedLeadId, setSelectedLeadId] = useState<string | null>(null)
  const [detail, setDetail] = useState<LeadDetailResponse | null>(null)
  const [detailLoading, setDetailLoading] = useState(false)
  const [detailError, setDetailError] = useState('')

  const ownerOptions = useMemo(
    () => Array.from(new Map(leads.map(lead => [lead.owner_id, lead.owner_display_name])).entries()),
    [leads]
  )
  const assigneeOptions = useMemo(
    () => teamUsers.map(user => [user.id, user.display_name] as const),
    [teamUsers]
  )

  const filteredLeads = useMemo(() => {
    let result = leads

    if (stageFilter !== 'all') {
      result = result.filter(lead => lead.status === stageFilter)
    }

    if (ownerFilter !== 'all') {
      result = result.filter(lead => lead.owner_id === ownerFilter)
    }

    if (assigneeFilter === 'unassigned') {
      result = result.filter(lead => !lead.assigned_to)
    } else if (assigneeFilter !== 'all') {
      result = result.filter(lead => lead.assigned_to === assigneeFilter)
    }

    if (followUpFilter === 'due') {
      const now = Date.now()
      result = result.filter(lead => lead.next_follow_up_at && new Date(lead.next_follow_up_at).getTime() <= now)
    }

    if (search.trim()) {
      const needle = search.toLowerCase()
      result = result.filter(lead =>
        lead.business_name.toLowerCase().includes(needle) ||
        lead.city.toLowerCase().includes(needle) ||
        lead.normalized_category.toLowerCase().includes(needle) ||
        lead.owner_display_name.toLowerCase().includes(needle) ||
        (lead.assigned_to_display_name ?? '').toLowerCase().includes(needle)
      )
    }

    return [...result].sort((left, right) => {
      const a = left[sortKey] ?? ''
      const b = right[sortKey] ?? ''

      if (sortKey === 'updated_at' || sortKey === 'next_follow_up_at') {
        const aTime = a ? new Date(String(a)).getTime() : 0
        const bTime = b ? new Date(String(b)).getTime() : 0
        return sortDir === 'asc' ? aTime - bTime : bTime - aTime
      }

      return sortDir === 'asc'
        ? String(a).localeCompare(String(b))
        : String(b).localeCompare(String(a))
    })
  }, [assigneeFilter, followUpFilter, leads, ownerFilter, search, sortDir, sortKey, stageFilter])

  useEffect(() => {
    if (!selectedLeadId && filteredLeads.length > 0) {
      setSelectedLeadId(filteredLeads[0].id)
      return
    }

    if (selectedLeadId && !filteredLeads.some(lead => lead.id === selectedLeadId)) {
      setSelectedLeadId(filteredLeads[0]?.id ?? null)
    }
  }, [filteredLeads, selectedLeadId])

  useEffect(() => {
    if (!selectedLeadId) {
      setDetail(null)
      return
    }

    setDetailLoading(true)
    setDetailError('')

    void fetchLeadDetail(selectedLeadId)
      .then(setDetail)
      .catch(err => setDetailError(err instanceof Error ? err.message : 'Unable to load lead detail'))
      .finally(() => setDetailLoading(false))
  }, [selectedLeadId])

  const stageCounts = useMemo(() => ({
    total: leads.length,
    followUps: leads.filter(lead => Boolean(lead.next_follow_up_at)).length,
    assigned: leads.filter(lead => Boolean(lead.assigned_to)).length,
    private: leads.filter(lead => lead.visibility_scope === 'private').length,
  }), [leads])

  const toggleSort = (key: SortKey) => {
    if (sortKey === key) {
      setSortDir(prev => prev === 'asc' ? 'desc' : 'asc')
      return
    }

    setSortKey(key)
    setSortDir(key === 'business_name' || key === 'owner_display_name' ? 'asc' : 'desc')
  }

  return (
    <div className="flex flex-1 overflow-hidden">
      <div className="flex-1 flex flex-col overflow-hidden">
        <div className="mx-6 mt-6 flex flex-wrap items-center gap-3">
          <button
            onClick={() => {
              setShowManualForm(prev => !prev)
              if (showBackupPanel) setShowBackupPanel(false)
            }}
            className={`rounded-xl px-4 py-3 text-sm font-black transition ${
              showManualForm
                ? 'bg-[#ffb2b9] text-[#390512]'
                : 'bg-[#131b2e] text-slate-200 hover:text-white'
            }`}
          >
            {showManualForm ? 'Hide Add Lead' : 'Add Lead'}
          </button>
          {canAccessLeadBackup(currentUser) && (
            <button
              onClick={() => {
                setShowBackupPanel(prev => !prev)
                if (showManualForm) setShowManualForm(false)
              }}
              className={`rounded-xl px-4 py-3 text-sm font-black transition ${
                showBackupPanel
                  ? 'bg-[#dae2fd] text-[#0b1326]'
                  : 'bg-[#131b2e] text-slate-200 hover:text-white'
              }`}
            >
              {showBackupPanel ? 'Hide Backup Tools' : 'Backup & Import'}
            </button>
          )}
          <p className="text-xs text-slate-500">
            Manage direct lead entry here. Full backup and restore tools are limited to admin roles.
          </p>
        </div>

        {libraryMessage && (
          <div className="mx-6 mt-4 rounded-xl border border-[#22c55e]/20 bg-[#22c55e]/10 px-4 py-3 text-sm text-[#9fe8c4]">
            {libraryMessage}
          </div>
        )}

        {showManualForm && (
          <ManualLeadForm
            currentUser={currentUser}
            teamUsers={teamUsers}
            onCreated={result => {
              setShowManualForm(false)
              setSelectedLeadId(result.lead.id)
              setLibraryMessage(result.created ? 'Manual lead created successfully.' : 'Lead already existed, so the existing record was opened instead of creating a duplicate.')
              onLeadUpdated(result.lead)
            }}
            onCancel={() => setShowManualForm(false)}
          />
        )}

        {showBackupPanel && canAccessLeadBackup(currentUser) && (
          <LeadBackupPanel
            onImported={onLibraryReload}
            onClose={() => setShowBackupPanel(false)}
          />
        )}

        <div className="mx-6 mt-6 grid grid-cols-2 gap-3 xl:grid-cols-5">
          {[
            ['Total Leads', String(stageCounts.total)],
            ['With Follow-up', String(stageCounts.followUps)],
            ['Follow-up Due', String(getFollowUpDueCount(leads))],
            ['Assigned', String(stageCounts.assigned)],
            ['Private', String(stageCounts.private)],
          ].map(([label, value]) => (
            <div key={label} className="bg-[#060e20] rounded-xl p-4 border border-[#574143]/10">
              <p className="text-[10px] font-black text-slate-500 uppercase tracking-widest mb-1">{label}</p>
              <p className="text-2xl font-black text-slate-100">{value}</p>
            </div>
          ))}
        </div>

        <div className="mx-6 mt-4 bg-[#060e20] rounded-xl overflow-hidden flex flex-col shadow-2xl border border-[#574143]/10">
          <div className="px-4 py-3 border-b border-[#574143]/10 flex items-center gap-2 flex-wrap">
            <input
              type="text"
              value={search}
              onChange={event => setSearch(event.target.value)}
              placeholder="Search library…"
              className="bg-[#131b2e] px-3 py-2 rounded-xl border border-[#574143]/10 text-xs text-[#dae2fd] focus:outline-none focus:ring-1 focus:ring-[#fb7185]/50 placeholder-slate-600 w-44"
            />

            <select
              value={stageFilter}
              onChange={event => setStageFilter(event.target.value as LeadPipelineStatus | 'all')}
              className="bg-[#131b2e] px-3 py-2 rounded-xl border border-[#574143]/10 text-xs text-[#dae2fd] focus:outline-none"
            >
              <option value="all">All Stages</option>
              {Object.entries(STAGE_LABELS).map(([value, label]) => (
                <option key={value} value={value}>{label}</option>
              ))}
            </select>

            <select
              value={ownerFilter}
              onChange={event => setOwnerFilter(event.target.value)}
              className="bg-[#131b2e] px-3 py-2 rounded-xl border border-[#574143]/10 text-xs text-[#dae2fd] focus:outline-none"
            >
              <option value="all">All Owners</option>
              {ownerOptions.map(([id, name]) => (
                <option key={id} value={id}>{name}</option>
              ))}
            </select>

            <select
              value={assigneeFilter}
              onChange={event => setAssigneeFilter(event.target.value)}
              className="bg-[#131b2e] px-3 py-2 rounded-xl border border-[#574143]/10 text-xs text-[#dae2fd] focus:outline-none"
            >
              <option value="all">All Assignees</option>
              <option value="unassigned">Unassigned</option>
              {assigneeOptions.map(([id, name]) => (
                <option key={id} value={id}>{name}</option>
              ))}
            </select>

            <select
              value={followUpFilter}
              onChange={event => setFollowUpFilter(event.target.value as FollowUpFilter)}
              className="bg-[#131b2e] px-3 py-2 rounded-xl border border-[#574143]/10 text-xs text-[#dae2fd] focus:outline-none"
            >
              <option value="all">All Leads</option>
              <option value="due">Follow-up Due</option>
            </select>

            <span className="ml-auto text-[11px] text-slate-500">
              {filteredLeads.length} of {leads.length}
            </span>
          </div>

          <div className="flex-1 overflow-auto">
            <table className="w-full text-left">
              <thead className="sticky top-0 bg-[#131b2e] z-10">
                <tr>
                  {([
                    ['business_name', 'Business'],
                    ['owner_display_name', 'Owner'],
                    ['assigned_to_display_name', 'Assigned'],
                    ['status', 'Stage'],
                    ['next_follow_up_at', 'Follow-up'],
                    ['updated_at', 'Updated'],
                  ] as [SortKey, string][]).map(([key, label]) => (
                    <th
                      key={key}
                      onClick={() => toggleSort(key)}
                      className="px-4 py-3 text-[10px] font-black text-slate-500 uppercase tracking-widest cursor-pointer"
                    >
                      {label}
                    </th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {filteredLeads.map(lead => (
                  <tr
                    key={lead.id}
                    onClick={() => setSelectedLeadId(lead.id)}
                    className={`cursor-pointer transition-colors border-b border-[#574143]/5 ${selectedLeadId === lead.id ? 'bg-[#ffb2b9]/5 border-l-4 border-l-[#ffb2b9]' : 'hover:bg-[#222a3d]/50'}`}
                  >
                    <td className="px-4 py-3">
                      <div className="flex flex-col">
                        <span className="text-sm font-bold text-[#dae2fd]">{lead.business_name}</span>
                        <span className="text-[10px] text-slate-500">{lead.normalized_category} · {lead.city || 'Unknown city'}</span>
                        <span className="text-[10px] text-slate-600">{formatLastContact(lead.last_contact_at)}</span>
                      </div>
                    </td>
                    <td className="px-4 py-3">
                      <div className="flex flex-col">
                        <span className="text-[12px] text-slate-200">{lead.owner_display_name}</span>
                        <span className="text-[10px] text-slate-500">{lead.owner_role}</span>
                      </div>
                    </td>
                    <td className="px-4 py-3">
                      <div className="flex flex-col">
                        <span className="text-[12px] text-slate-200">{lead.assigned_to_display_name ?? 'Unassigned'}</span>
                        <span className="text-[10px] text-slate-500">{lead.visibility_scope === 'private' ? 'Private' : 'Shared'}</span>
                      </div>
                    </td>
                    <td className="px-4 py-3">
                      <div className="flex flex-col gap-1">
                        <span className={`px-2 py-1 text-[10px] font-black rounded-full uppercase tracking-widest ${STAGE_STYLES[lead.status]}`}>
                          {STAGE_LABELS[lead.status]}
                        </span>
                        <span className={`inline-flex w-fit px-2 py-1 text-[9px] font-black rounded-full uppercase tracking-widest ${getOutreachStatus(lead).style}`}>
                          {getOutreachStatus(lead).label}
                        </span>
                      </div>
                    </td>
                    <td className="px-4 py-3 text-[12px] text-slate-300">{formatDateShort(lead.next_follow_up_at)}</td>
                    <td className="px-4 py-3 text-[12px] text-slate-400">{formatDateShort(lead.updated_at)}</td>
                  </tr>
                ))}
              </tbody>
            </table>

            {filteredLeads.length === 0 && (
              <div className="p-10 text-center text-slate-500 text-sm">
                No saved CRM leads match the current filters yet.
              </div>
            )}
          </div>
        </div>
      </div>

      {detailLoading ? (
        <aside className="w-96 bg-[#171f33] border-l border-[#574143]/10 flex items-center justify-center">
          <span className="material-symbols-outlined animate-spin text-[#fb7185] text-3xl">refresh</span>
        </aside>
      ) : detailError ? (
        <aside className="w-96 bg-[#171f33] border-l border-[#574143]/10 flex items-center justify-center p-8 text-center">
          <div>
            <span className="material-symbols-outlined text-5xl text-red-400 mb-4">error</span>
            <p className="text-sm text-red-300">{detailError}</p>
          </div>
        </aside>
      ) : (
          <LeadCRMPanel
            detail={detail}
            teamUsers={teamUsers}
            currentUser={currentUser}
            outreachConfig={outreachConfig}
            onClose={() => setSelectedLeadId(null)}
          onDetailUpdated={updatedDetail => {
            setDetail(updatedDetail)
            onLeadUpdated(updatedDetail.lead)
          }}
        />
      )}
    </div>
  )
}
