import { useEffect, useState } from 'react'
import { Plug, CheckCircle2, AlertCircle, Loader2, Pencil, Trash2, Shield, History, Ticket, Users, Zap, Save, Bell } from 'lucide-react'
import { NotificationSettings } from '@/components/account/NotificationSettings'
import { analytics } from '@/lib/analytics'
import { EmptyState } from '@/components/common/EmptyState'
import { IntegrationIllustration } from '@/components/common/EmptyStateIllustrations'
import { PageMeta } from '@/components/common/PageMeta'
import { integrationsApi } from '@/api/integrations'
import type { PsaConnectionResponse, PsaConnectionCreate, PsaConnectionUpdate, PsaConnectionTestResponse } from '@/types'
import type { PsaMemberResponse, PsaMemberMappingResponse } from '@/types/integrations'
import { toast } from '@/lib/toast'
import { cn } from '@/lib/utils'
import { Input } from '@/components/ui/Input'

function formatRelativeTime(dateStr: string): string {
  const date = new Date(dateStr)
  const now = new Date()
  const diffMs = now.getTime() - date.getTime()
  const diffMins = Math.floor(diffMs / 60000)
  if (diffMins < 1) return 'Just now'
  if (diffMins < 60) return `${diffMins}m ago`
  const diffHours = Math.floor(diffMins / 60)
  if (diffHours < 24) return `${diffHours}h ago`
  const diffDays = Math.floor(diffHours / 24)
  if (diffDays < 30) return `${diffDays}d ago`
  return date.toLocaleDateString()
}

interface ConnectionForm {
  display_name: string
  site_url: string
  company_id: string
  public_key: string
  private_key: string
}

const emptyForm: ConnectionForm = {
  display_name: '',
  site_url: '',
  company_id: '',
  public_key: '',
  private_key: '',
}

type Tab = 'connection' | 'member-mapping' | 'post-history' | 'flowpilot-settings' | 'notifications'

export function IntegrationsPage() {
  const [activeTab, setActiveTab] = useState<Tab>('connection')
  const [connection, setConnection] = useState<PsaConnectionResponse | null>(null)
  const [isLoading, setIsLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)

  // Form state
  const [mode, setMode] = useState<'view' | 'setup' | 'edit'>('setup')
  const [form, setForm] = useState<ConnectionForm>(emptyForm)
  const [isSaving, setIsSaving] = useState(false)
  const [formError, setFormError] = useState<string | null>(null)

  // Test state
  const [isTesting, setIsTesting] = useState(false)
  const [testResult, setTestResult] = useState<PsaConnectionTestResponse | null>(null)

  // Delete state
  const [isDeleting, setIsDeleting] = useState(false)
  const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)

  useEffect(() => {
    loadConnection()
  }, [])

  const loadConnection = async () => {
    setIsLoading(true)
    setError(null)
    try {
      const data = await integrationsApi.getConnection()
      setConnection(data)
      setMode(data ? 'view' : 'setup')
    } catch (err) {
      // 404 means no connection exists — that's fine
      const axiosErr = err as { response?: { status?: number } }
      if (axiosErr.response?.status === 404) {
        setConnection(null)
        setMode('setup')
      } else {
        setError('Failed to load integration settings')
        console.error(err)
      }
    } finally {
      setIsLoading(false)
    }
  }

  const handleCreate = async (e: React.FormEvent) => {
    e.preventDefault()
    setIsSaving(true)
    setFormError(null)
    try {
      const payload: PsaConnectionCreate = {
        provider: 'connectwise',
        ...form,
      }
      const created = await integrationsApi.createConnection(payload)
      setConnection(created)
      analytics.psaConnected({ provider: 'connectwise' })
      setMode('view')
      setForm(emptyForm)
    } catch (err) {
      const axiosErr = err as { response?: { data?: { detail?: string } } }
      setFormError(axiosErr.response?.data?.detail || 'Failed to create connection. Please check your credentials and try again.')
      console.error(err)
    } finally {
      setIsSaving(false)
    }
  }

  const handleUpdate = async (e: React.FormEvent) => {
    e.preventDefault()
    if (!connection) return
    setIsSaving(true)
    setFormError(null)
    try {
      const update: PsaConnectionUpdate = {}
      if (form.display_name && form.display_name !== connection.display_name) update.display_name = form.display_name
      if (form.site_url && form.site_url !== connection.site_url) update.site_url = form.site_url
      if (form.company_id && form.company_id !== connection.company_id) update.company_id = form.company_id
      if (form.public_key) update.public_key = form.public_key
      if (form.private_key) update.private_key = form.private_key
      // client_id is server-side (settings.CW_CLIENT_ID), not per-account

      const updated = await integrationsApi.updateConnection(connection.id, update)
      setConnection(updated)
      setMode('view')
      setForm(emptyForm)
    } catch (err) {
      const axiosErr = err as { response?: { data?: { detail?: string } } }
      setFormError(axiosErr.response?.data?.detail || 'Failed to update connection.')
      console.error(err)
    } finally {
      setIsSaving(false)
    }
  }

  const handleTest = async () => {
    if (!connection) return
    setIsTesting(true)
    setTestResult(null)
    try {
      const result = await integrationsApi.testConnection(connection.id)
      setTestResult(result)
    } catch (err) {
      setTestResult({ success: false, message: 'Connection test failed. Check your credentials.', server_version: null })
      console.error(err)
    } finally {
      setIsTesting(false)
    }
  }

  const handleDelete = async () => {
    if (!connection) return
    setIsDeleting(true)
    try {
      await integrationsApi.deleteConnection(connection.id)
      setConnection(null)
      setMode('setup')
      setForm(emptyForm)
      setShowDeleteConfirm(false)
      setTestResult(null)
    } catch (err) {
      console.error('Failed to delete connection:', err)
    } finally {
      setIsDeleting(false)
    }
  }

  const startEdit = () => {
    if (!connection) return
    setForm({
      display_name: connection.display_name,
      site_url: connection.site_url,
      company_id: connection.company_id,
      public_key: '',
      private_key: '',
    })
    setFormError(null)
    setTestResult(null)
    setMode('edit')
  }

  const cancelEdit = () => {
    setMode('view')
    setForm(emptyForm)
    setFormError(null)
  }

  if (isLoading) {
    return (
      <>
        <PageMeta title="Integrations" />
        <div className="flex justify-center py-12">
          <Loader2 className="h-8 w-8 animate-spin text-[#848b9b]" />
        </div>
      </>
    )
  }

  if (error) {
    return (
      <>
        <PageMeta title="Integrations" />
        <div className="rounded-md border border-red-400/20 bg-red-400/10 p-4 text-red-400">
          <div className="flex items-center gap-2">
            <AlertCircle className="h-5 w-5" />
            {error}
          </div>
        </div>
      </>
    )
  }

  return (
    <>
      <PageMeta title="Integrations" />
      <div>
        <div className="mb-8">
          <div className="flex items-center gap-3">
            <Plug className="h-8 w-8 text-[#848b9b]" />
            <h1 className="text-2xl font-bold font-heading text-[#e2e5eb] sm:text-3xl">Integrations</h1>
          </div>
          <p className="mt-2 text-[#848b9b]">
            Connect your PSA to post session documentation directly to tickets.
          </p>
        </div>

        {/* Tabs */}
        <div className="mb-6 flex gap-1 border-b border-[#1e2130]">
          {([
            { id: 'connection' as Tab, label: 'Connection', icon: Plug },
            { id: 'member-mapping' as Tab, label: 'Member Mapping', icon: Users },
            { id: 'post-history' as Tab, label: 'Post History', icon: History },
            { id: 'flowpilot-settings' as Tab, label: 'FlowPilot', icon: Zap },
            { id: 'notifications' as Tab, label: 'Notifications', icon: Bell },
          ]).map(({ id, label, icon: Icon }) => (
            <button
              key={id}
              onClick={() => setActiveTab(id)}
              className={cn(
                'inline-flex items-center gap-2 border-b-2 px-4 py-2.5 text-sm font-medium transition-colors -mb-px',
                activeTab === id
                  ? 'border-primary text-[#e2e5eb]'
                  : 'border-transparent text-[#848b9b] hover:text-[#e2e5eb] hover:border-[#1e2130]'
              )}
            >
              <Icon className="h-4 w-4" />
              {label}
            </button>
          ))}
        </div>

        {/* Connection Tab */}
        {activeTab === 'connection' && (
        <div className="max-w-3xl">
          {/* PSA Provider Grid */}
          <div className="mb-6">
            <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b] mb-3">
              Available PSA Integrations
            </p>
            <div className="grid grid-cols-1 gap-3 sm:grid-cols-3">
              {/* ConnectWise — active */}
              <div className={cn(
                'rounded-xl border p-4 flex flex-col gap-2',
                connection
                  ? 'border-primary/40 bg-primary/5'
                  : 'border-[#1e2130] bg-[#14161d]/30'
              )}>
                <div className="flex items-center justify-between">
                  <span className="text-sm font-medium text-[#e2e5eb]">ConnectWise PSA</span>
                  {connection ? (
                    <span className="inline-flex items-center rounded-full bg-emerald-400/10 px-2 py-0.5 text-[0.625rem] font-sans text-xs text-emerald-400">
                      Connected
                    </span>
                  ) : (
                    <span className="inline-flex items-center rounded-full bg-[rgba(34,211,238,0.10)] px-2 py-0.5 text-[0.625rem] font-sans text-xs text-[#22d3ee]">
                      Available
                    </span>
                  )}
                </div>
                <p className="text-xs text-[#848b9b]">Manage, ticket linking, time entries</p>
              </div>

              {/* Autotask — coming soon */}
              <div className="rounded-xl border border-[#1e2130] bg-[#14161d]/20 p-4 flex flex-col gap-2 opacity-60 cursor-not-allowed select-none">
                <div className="flex items-center justify-between">
                  <span className="text-sm font-medium text-[#e2e5eb]">Autotask PSA</span>
                  <span className="inline-flex items-center rounded-full bg-amber-400/10 px-2 py-0.5 text-[0.625rem] font-sans text-xs text-amber-400">
                    Coming Soon
                  </span>
                </div>
                <p className="text-xs text-[#848b9b]">Datto / Kaseya integration</p>
              </div>

              {/* Halo PSA — coming soon */}
              <div className="rounded-xl border border-[#1e2130] bg-[#14161d]/20 p-4 flex flex-col gap-2 opacity-60 cursor-not-allowed select-none">
                <div className="flex items-center justify-between">
                  <span className="text-sm font-medium text-[#e2e5eb]">Halo PSA</span>
                  <span className="inline-flex items-center rounded-full bg-amber-400/10 px-2 py-0.5 text-[0.625rem] font-sans text-xs text-amber-400">
                    Coming Soon
                  </span>
                </div>
                <p className="text-xs text-[#848b9b]">HaloPSA / HaloITSM integration</p>
              </div>
            </div>
          </div>

          {/* Illustrative empty state when no connection exists */}
          {mode === 'setup' && (
            <div className="mb-6">
              <EmptyState
                illustration={<IntegrationIllustration />}
                title="Connect your PSA for seamless workflows"
                description="Link ConnectWise or other PSA tools to pull ticket context into sessions and push documentation back automatically."
                learnMoreLink="/guides/psa-setup"
              />
            </div>
          )}

          {/* Setup / Edit Form */}
          {(mode === 'setup' || mode === 'edit') && (
            <div className="card-flat p-6">
              <div className="flex items-center gap-2 mb-6">
                <Shield className="h-5 w-5 text-[#848b9b]" />
                <h2 className="text-lg font-semibold text-[#e2e5eb]">
                  {mode === 'setup' ? 'Connect to ConnectWise PSA' : 'Edit Connection'}
                </h2>
              </div>

              <form onSubmit={mode === 'setup' ? handleCreate : handleUpdate} className="space-y-4">
                <div>
                  <label className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">
                    Display Name
                  </label>
                  <Input
                    type="text"
                    value={form.display_name}
                    onChange={(e) => setForm({ ...form, display_name: e.target.value })}
                    placeholder="My ConnectWise Instance"
                    required={mode === 'setup'}
                    className="mt-1"
                  />
                </div>

                <div>
                  <label className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">
                    Site URL
                  </label>
                  <Input
                    type="text"
                    value={form.site_url}
                    onChange={(e) => setForm({ ...form, site_url: e.target.value })}
                    placeholder="na.myconnectwise.net"
                    required={mode === 'setup'}
                    className="mt-1"
                  />
                </div>

                <div>
                  <label className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">
                    Company ID
                  </label>
                  <Input
                    type="text"
                    value={form.company_id}
                    onChange={(e) => setForm({ ...form, company_id: e.target.value })}
                    placeholder="mycompany"
                    required={mode === 'setup'}
                    className="mt-1"
                  />
                </div>

                <div>
                  <label className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">
                    Public Key
                  </label>
                  <Input
                    type="text"
                    value={form.public_key}
                    onChange={(e) => setForm({ ...form, public_key: e.target.value })}
                    placeholder={mode === 'edit' && connection ? `Current: ${connection.public_key_hint}` : 'Enter public key'}
                    required={mode === 'setup'}
                    className="mt-1"
                  />
                </div>

                <div>
                  <label className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">
                    Private Key
                  </label>
                  <Input
                    type="password"
                    value={form.private_key}
                    onChange={(e) => setForm({ ...form, private_key: e.target.value })}
                    placeholder={mode === 'edit' && connection ? `Current: ${connection.private_key_hint}` : 'Enter private key'}
                    required={mode === 'setup'}
                    className="mt-1"
                  />
                </div>

                {formError && (
                  <div className="flex items-center gap-2 rounded-md border border-red-400/20 bg-red-400/10 p-3 text-sm text-red-400">
                    <AlertCircle className="h-4 w-4 shrink-0" />
                    {formError}
                  </div>
                )}

                <div className="flex items-center gap-3 pt-2">
                  <button
                    type="submit"
                    disabled={isSaving}
                    className={cn(
                      'inline-flex items-center gap-2 rounded-lg px-5 py-2.5 text-sm font-semibold',
                      'bg-[#22d3ee] text-white',
                      'hover:brightness-110 active:scale-[0.98] transition-all',
                      'disabled:opacity-50 disabled:cursor-not-allowed'
                    )}
                  >
                    {isSaving && <Loader2 className="h-4 w-4 animate-spin" />}
                    {mode === 'setup' ? 'Connect' : 'Save Changes'}
                  </button>

                  {mode === 'edit' && (
                    <button
                      type="button"
                      onClick={cancelEdit}
                      className="text-sm text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
                    >
                      Cancel
                    </button>
                  )}
                </div>
              </form>
            </div>
          )}

          {/* Connected View */}
          {mode === 'view' && connection && (
            <div className="space-y-4">
              {/* Status Card */}
              <div className="card-flat p-6">
                <div className="flex items-center justify-between mb-4">
                  <div className="flex items-center gap-3">
                    <span className="inline-flex items-center rounded-full bg-[rgba(34,211,238,0.10)] px-2.5 py-0.5 text-xs font-sans text-xs font-medium text-[#22d3ee]">
                      ConnectWise
                    </span>
                    <h2 className="text-lg font-semibold text-[#e2e5eb]">{connection.display_name}</h2>
                  </div>
                  <div className="flex items-center gap-2">
                    <span
                      className={cn(
                        'inline-flex h-2 w-2 rounded-full',
                        connection.is_active ? 'bg-emerald-400' : 'bg-amber-400'
                      )}
                    />
                    <span className={cn(
                      'text-xs font-sans text-xs',
                      connection.is_active ? 'text-emerald-400' : 'text-amber-400'
                    )}>
                      {connection.is_active ? 'Connected' : 'Not validated'}
                    </span>
                  </div>
                </div>

                <div className="grid gap-4 sm:grid-cols-2">
                  <div>
                    <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">Site URL</p>
                    <p className="mt-1 text-sm text-[#e2e5eb]">{connection.site_url}</p>
                  </div>
                  <div>
                    <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">Company ID</p>
                    <p className="mt-1 text-sm text-[#e2e5eb]">{connection.company_id}</p>
                  </div>
                  <div>
                    <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">Public Key</p>
                    <p className="mt-1 text-sm text-[#e2e5eb] font-mono">{connection.public_key_hint}</p>
                  </div>
                  <div>
                    <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">Private Key</p>
                    <p className="mt-1 text-sm text-[#e2e5eb] font-mono">{connection.private_key_hint}</p>
                  </div>
                  <div>
                    <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">Last Validated</p>
                    <p className="mt-1 text-sm text-[#e2e5eb]">
                      {connection.last_validated_at ? formatRelativeTime(connection.last_validated_at) : 'Never'}
                    </p>
                  </div>
                </div>
              </div>

              {/* Test Result */}
              {testResult && (
                <div
                  className={cn(
                    'flex items-center gap-2 rounded-xl border p-4 text-sm',
                    testResult.success
                      ? 'border-emerald-400/20 bg-emerald-400/10 text-emerald-400'
                      : 'border-red-400/20 bg-red-400/10 text-red-400'
                  )}
                >
                  {testResult.success ? (
                    <CheckCircle2 className="h-4 w-4 shrink-0" />
                  ) : (
                    <AlertCircle className="h-4 w-4 shrink-0" />
                  )}
                  <span>{testResult.message}</span>
                  {testResult.server_version && (
                    <span className="ml-auto text-xs text-[#848b9b]">
                      v{testResult.server_version}
                    </span>
                  )}
                </div>
              )}

              {/* Action Buttons */}
              <div className="flex items-center gap-3">
                <button
                  onClick={handleTest}
                  disabled={isTesting}
                  className={cn(
                    'inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium',
                    'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb]',
                    'hover:border-[rgba(255,255,255,0.12)] transition-all',
                    'disabled:opacity-50 disabled:cursor-not-allowed'
                  )}
                >
                  {isTesting ? (
                    <Loader2 className="h-4 w-4 animate-spin" />
                  ) : (
                    <CheckCircle2 className="h-4 w-4" />
                  )}
                  Test Connection
                </button>

                <button
                  onClick={startEdit}
                  className={cn(
                    'inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium',
                    'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb]',
                    'hover:border-[rgba(255,255,255,0.12)] transition-all'
                  )}
                >
                  <Pencil className="h-4 w-4" />
                  Edit
                </button>

                {showDeleteConfirm ? (
                  <div className="flex items-center gap-2 ml-auto">
                    <span className="text-sm text-[#848b9b]">Disconnect?</span>
                    <button
                      onClick={handleDelete}
                      disabled={isDeleting}
                      className="inline-flex items-center gap-1.5 rounded-lg px-3 py-2 text-sm font-medium text-red-400 hover:bg-red-400/10 transition-colors"
                    >
                      {isDeleting ? <Loader2 className="h-4 w-4 animate-spin" /> : <Trash2 className="h-4 w-4" />}
                      Confirm
                    </button>
                    <button
                      onClick={() => setShowDeleteConfirm(false)}
                      className="text-sm text-[#848b9b] hover:text-[#e2e5eb] transition-colors"
                    >
                      Cancel
                    </button>
                  </div>
                ) : (
                  <button
                    onClick={() => setShowDeleteConfirm(true)}
                    className="inline-flex items-center gap-2 ml-auto text-sm text-red-400 hover:text-red-300 transition-colors"
                  >
                    <Trash2 className="h-4 w-4" />
                    Disconnect
                  </button>
                )}
              </div>
            </div>
          )}
        </div>
        )}

        {/* Member Mapping Tab */}
        {activeTab === 'member-mapping' && (
          <MemberMappingTab connection={connection} />
        )}

        {/* Post History Tab */}
        {activeTab === 'post-history' && (
          <div className="max-w-3xl">
            <div className="card-flat p-6">
              <div className="flex items-center gap-3 mb-4">
                <Ticket className="h-5 w-5 text-[#848b9b]" />
                <h2 className="text-lg font-semibold text-[#e2e5eb]">Post History</h2>
              </div>
              <p className="text-sm text-[#848b9b]">
                View post history from individual sessions by clicking on linked tickets.
                When a session has a ConnectWise ticket linked, use the Update button to post
                session documentation and view previous posts.
              </p>
            </div>
          </div>
        )}

        {/* FlowPilot Settings Tab */}
        {activeTab === 'flowpilot-settings' && (
          <FlowPilotSettingsTab connection={connection} />
        )}

        {/* Notifications Tab */}
        {activeTab === 'notifications' && (
          <NotificationSettings />
        )}
      </div>
    </>
  )
}

/* ─── Member Mapping Tab ─── */

function MemberMappingTab({ connection }: { connection: PsaConnectionResponse | null }) {
  const [cwMembers, setCwMembers] = useState<PsaMemberResponse[]>([])
  const [mappings, setMappings] = useState<PsaMemberMappingResponse[]>([])
  const [localMappings, setLocalMappings] = useState<Record<string, { external_member_id: string; external_member_name: string }>>({})
  const [isLoadingData, setIsLoadingData] = useState(false)
  const [isAutoMatching, setIsAutoMatching] = useState(false)
  const [isSavingMappings, setIsSavingMappings] = useState(false)
  const [isDirty, setIsDirty] = useState(false)
  const [hasLoaded, setHasLoaded] = useState(false)

  useEffect(() => {
    if (connection) {
      loadMappingData()
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [connection?.id])

  const loadMappingData = async () => {
    setIsLoadingData(true)
    try {
      const [members, existingMappings] = await Promise.all([
        integrationsApi.listMembers(),
        integrationsApi.getMemberMappings(),
      ])
      setCwMembers(members)
      setMappings(existingMappings)

      // Build local mapping state from existing mappings
      const lookup: Record<string, { external_member_id: string; external_member_name: string }> = {}
      for (const m of existingMappings) {
        lookup[m.user_id] = { external_member_id: m.external_member_id, external_member_name: m.external_member_name }
      }
      setLocalMappings(lookup)
      setIsDirty(false)
      setHasLoaded(true)
    } catch (err) {
      console.error('Failed to load mapping data:', err)
      toast.error('Failed to load member data')
    } finally {
      setIsLoadingData(false)
    }
  }

  const handleAutoMatch = async () => {
    setIsAutoMatching(true)
    try {
      const result = await integrationsApi.autoMatchMembers()
      toast.success(`Matched ${result.matched.length} user${result.matched.length !== 1 ? 's' : ''}${result.unmatched_users > 0 ? `, ${result.unmatched_users} remain unmapped` : ''}`)
      await loadMappingData()
    } catch (err) {
      console.error('Auto-match failed:', err)
      toast.error('Auto-match failed')
    } finally {
      setIsAutoMatching(false)
    }
  }

  const handleMemberChange = (userId: string, externalMemberId: string) => {
    setLocalMappings(prev => {
      const next = { ...prev }
      if (!externalMemberId) {
        delete next[userId]
      } else {
        const member = cwMembers.find(m => m.id === externalMemberId)
        next[userId] = {
          external_member_id: externalMemberId,
          external_member_name: member?.name || '',
        }
      }
      return next
    })
    setIsDirty(true)
  }

  const handleSave = async () => {
    setIsSavingMappings(true)
    try {
      const payload = Object.entries(localMappings).map(([user_id, mapping]) => ({
        user_id,
        external_member_id: mapping.external_member_id,
        external_member_name: mapping.external_member_name,
      }))
      await integrationsApi.saveMemberMappings(payload)
      toast.success('Member mappings saved')
      setIsDirty(false)
      // Reload to get fresh data with matched_by etc.
      await loadMappingData()
    } catch (err) {
      console.error('Failed to save mappings:', err)
      toast.error('Failed to save mappings')
    } finally {
      setIsSavingMappings(false)
    }
  }

  // Derive user list from mappings response (all account users are returned)
  const userRows = mappings.length > 0
    ? mappings.map(m => ({ user_id: m.user_id, user_email: m.user_email, user_name: m.user_name, matched_by: m.matched_by }))
    : []

  // Deduplicate: mappings may only contain mapped users, so we show what we have
  const uniqueUsers = hasLoaded ? userRows : []

  if (!connection) {
    return (
      <div className="max-w-3xl">
        <div className="card-flat p-6">
          <div className="flex items-center gap-3 mb-4">
            <Users className="h-5 w-5 text-[#848b9b]" />
            <h2 className="text-lg font-semibold text-[#e2e5eb]">Member Mapping</h2>
          </div>
          <p className="text-sm text-[#848b9b]">
            Set up a PSA connection first to map team members to ConnectWise members.
          </p>
        </div>
      </div>
    )
  }

  return (
    <div className="max-w-3xl space-y-4">
      {/* Header + Auto-Match */}
      <div className="card-flat p-6">
        <div className="flex items-center justify-between mb-2">
          <div className="flex items-center gap-3">
            <Users className="h-5 w-5 text-[#848b9b]" />
            <h2 className="text-lg font-semibold text-[#e2e5eb]">Member Mapping</h2>
          </div>
          <button
            type="button"
            onClick={handleAutoMatch}
            disabled={isAutoMatching || isLoadingData}
            className={cn(
              'inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium',
              'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb]',
              'hover:border-[rgba(255,255,255,0.12)] transition-all',
              'disabled:opacity-50 disabled:cursor-not-allowed'
            )}
          >
            {isAutoMatching ? (
              <Loader2 className="h-4 w-4 animate-spin" />
            ) : (
              <Zap className="h-4 w-4" />
            )}
            Auto-Match by Email
          </button>
        </div>
        <p className="text-sm text-[#848b9b]">
          Map your ResolutionFlow users to ConnectWise members so session posts are attributed correctly.
        </p>
      </div>

      {/* Loading state */}
      {isLoadingData && (
        <div className="flex justify-center py-8">
          <Loader2 className="h-6 w-6 animate-spin text-[#848b9b]" />
        </div>
      )}

      {/* Mapping Table */}
      {hasLoaded && !isLoadingData && (
        <div className="card-flat overflow-hidden">
          {uniqueUsers.length === 0 ? (
            <div className="p-6 text-center text-sm text-[#848b9b]">
              No users found. Use Auto-Match to discover and map users.
            </div>
          ) : (
            <>
              {/* Table header */}
              <div className="grid grid-cols-[1fr_1fr_1fr_auto] gap-4 border-b border-[#1e2130] px-6 py-3">
                <span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">User</span>
                <span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">Email</span>
                <span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]">Mapped To</span>
                <span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b] w-20 text-center">Method</span>
              </div>

              {/* Rows */}
              {uniqueUsers.map((user) => {
                const currentMapping = localMappings[user.user_id]
                return (
                  <div
                    key={user.user_id}
                    className="grid grid-cols-[1fr_1fr_1fr_auto] gap-4 items-center border-b border-[#1e2130]/50 px-6 py-3 last:border-b-0"
                  >
                    <span className="text-sm text-[#e2e5eb] truncate">{user.user_name}</span>
                    <span className="text-sm text-[#848b9b] truncate">{user.user_email}</span>
                    <select
                      title={`Map ${user.user_name} to a ConnectWise member`}
                      value={currentMapping?.external_member_id || ''}
                      onChange={(e) => handleMemberChange(user.user_id, e.target.value)}
                      className={cn(
                        'w-full rounded-lg border bg-[#14161d] px-3 py-1.5 text-sm text-[#e2e5eb]',
                        'border-[#1e2130] focus:border-[rgba(6,182,212,0.3)] focus:outline-none',
                        !currentMapping && 'text-[#848b9b]'
                      )}
                    >
                      <option value="">-- Unmapped --</option>
                      {cwMembers.map((member) => (
                        <option key={member.id} value={member.id}>
                          {member.name}{member.email ? ` (${member.email})` : ''}
                        </option>
                      ))}
                    </select>
                    <span className="w-20 text-center">
                      {currentMapping && !isDirty && user.matched_by ? (
                        <span className={cn(
                          'inline-flex items-center rounded-full px-2 py-0.5 text-[0.625rem] font-sans text-xs',
                          user.matched_by === 'auto_email'
                            ? 'bg-[rgba(34,211,238,0.10)] text-[#22d3ee]'
                            : 'bg-[#14161d] border border-[#1e2130] text-[#848b9b]'
                        )}>
                          {user.matched_by === 'auto_email' ? 'auto' : 'manual'}
                        </span>
                      ) : currentMapping ? (
                        <span className="inline-flex items-center rounded-full px-2 py-0.5 text-[0.625rem] font-sans text-xs bg-[#14161d] border border-[#1e2130] text-[#848b9b]">
                          manual
                        </span>
                      ) : (
                        <span className="text-[0.625rem] text-[#848b9b]/50">—</span>
                      )}
                    </span>
                  </div>
                )
              })}
            </>
          )}
        </div>
      )}

      {/* Save button */}
      {isDirty && (
        <div className="flex justify-end">
          <button
            type="button"
            onClick={handleSave}
            disabled={isSavingMappings}
            className={cn(
              'inline-flex items-center gap-2 rounded-lg px-5 py-2.5 text-sm font-semibold',
              'bg-[#22d3ee] text-white',
              'hover:brightness-110 active:scale-[0.98] transition-all',
              'disabled:opacity-50 disabled:cursor-not-allowed'
            )}
          >
            {isSavingMappings ? (
              <Loader2 className="h-4 w-4 animate-spin" />
            ) : (
              <Save className="h-4 w-4" />
            )}
            Save Mappings
          </button>
        </div>
      )}
    </div>
  )
}

/* ─── FlowPilot Settings Tab ─── */

function FlowPilotSettingsTab({ connection }: { connection: PsaConnectionResponse | null }) {
  const [settings, setSettings] = useState<Record<string, unknown> | null>(null)
  const [isLoading, setIsLoading] = useState(true)
  const [isSaving, setIsSaving] = useState(false)

  useEffect(() => {
    if (!connection) {
      setIsLoading(false)
      return
    }
    integrationsApi.getFlowpilotSettings(connection.id)
      .then(s => setSettings(s as unknown as Record<string, unknown>))
      .catch(() => toast.error('Failed to load FlowPilot settings'))
      .finally(() => setIsLoading(false))
  }, [connection])

  const updateSetting = async (key: string, value: unknown) => {
    if (!connection || !settings) return
    const updated = { ...settings, [key]: value }
    setSettings(updated)
    setIsSaving(true)
    try {
      await integrationsApi.updateFlowpilotSettings(connection.id, { [key]: value })
    } catch {
      toast.error('Failed to save setting')
      // Revert
      setSettings(settings)
    } finally {
      setIsSaving(false)
    }
  }

  if (!connection) {
    return (
      <div className="max-w-3xl">
        <div className="card-flat p-6 text-center">
          <p className="text-sm text-[#848b9b]">Connect your PSA first to configure FlowPilot settings.</p>
        </div>
      </div>
    )
  }

  if (isLoading) {
    return (
      <div className="flex justify-center py-12">
        <Loader2 className="h-5 w-5 animate-spin text-[#848b9b]" />
      </div>
    )
  }

  if (!settings) return null

  return (
    <div className="max-w-3xl space-y-4">
      <div className="card-flat p-6">
        <div className="flex items-center gap-3 mb-4">
          <Zap className="h-5 w-5 text-[#22d3ee]" />
          <h2 className="text-lg font-semibold text-[#e2e5eb]">FlowPilot Settings</h2>
        </div>
        <p className="text-sm text-[#848b9b] mb-6">
          Configure how FlowPilot integrates with your ConnectWise PSA when sessions are resolved or escalated.
        </p>

        <div className="space-y-5">
          {/* Auto-push documentation */}
          <SettingToggle
            label="Auto-push documentation"
            description="Automatically push session documentation to linked tickets on resolution"
            checked={settings.auto_push as boolean}
            onChange={(v) => updateSetting('auto_push', v)}
            disabled={isSaving}
          />

          {/* Auto-create time entry */}
          <SettingToggle
            label="Auto-create time entry"
            description="Automatically create a time entry when resolving (requires CW member mapping)"
            checked={settings.auto_time_entry as boolean}
            onChange={(v) => updateSetting('auto_time_entry', v)}
            disabled={isSaving}
          />

          {/* Time rounding */}
          <SettingSelect
            label="Time rounding"
            description="How to round session duration for time entries"
            value={settings.time_rounding as string}
            options={[
              { value: '15min', label: 'Nearest 15 minutes' },
              { value: '30min', label: 'Nearest 30 minutes' },
              { value: 'exact', label: 'Exact time' },
              { value: 'none', label: "Don't create time entries" },
            ]}
            onChange={(v) => updateSetting('time_rounding', v)}
            disabled={isSaving}
          />

          {/* Note visibility */}
          <SettingSelect
            label="Default note visibility"
            description="Who can see the session notes posted to tickets"
            value={settings.note_visibility as string}
            options={[
              { value: 'internal', label: 'Internal only' },
              { value: 'both', label: 'Internal and external' },
            ]}
            onChange={(v) => updateSetting('note_visibility', v)}
            disabled={isSaving}
          />

          {/* Include diagnostic steps */}
          <SettingToggle
            label="Include diagnostic steps in notes"
            description="When off, only push the summary — not the full diagnostic trail"
            checked={settings.include_diagnostic_steps as boolean}
            onChange={(v) => updateSetting('include_diagnostic_steps', v)}
            disabled={isSaving}
          />

          {/* Prompt for status on resolution */}
          <SettingToggle
            label="Prompt for ticket status on resolution"
            description="Show a status dropdown when resolving — options pulled from the ticket's board"
            checked={settings.prompt_status_on_resolution as boolean}
            onChange={(v) => updateSetting('prompt_status_on_resolution', v)}
            disabled={isSaving}
          />

          {/* Prompt for status on escalation */}
          <SettingToggle
            label="Prompt for ticket status on escalation"
            description="Show a status dropdown when escalating — options pulled from the ticket's board"
            checked={settings.prompt_status_on_escalation as boolean}
            onChange={(v) => updateSetting('prompt_status_on_escalation', v)}
            disabled={isSaving}
          />
        </div>
      </div>
    </div>
  )
}

/* ─── Setting Components ─── */

function SettingToggle({
  label,
  description,
  checked,
  onChange,
  disabled,
}: {
  label: string
  description: string
  checked: boolean
  onChange: (value: boolean) => void
  disabled?: boolean
}) {
  return (
    <div className="flex items-start justify-between gap-4">
      <div>
        <p className="text-sm font-medium text-[#e2e5eb]">{label}</p>
        <p className="text-xs text-[#848b9b] mt-0.5">{description}</p>
      </div>
      <button
        onClick={() => onChange(!checked)}
        disabled={disabled}
        className={cn(
          'relative inline-flex h-5 w-9 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors focus-visible:outline-none disabled:opacity-50',
          checked ? 'bg-primary' : 'bg-[rgba(255,255,255,0.1)]'
        )}
      >
        <span
          className={cn(
            'pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow-lg ring-0 transition-transform',
            checked ? 'translate-x-4' : 'translate-x-0'
          )}
        />
      </button>
    </div>
  )
}

function SettingSelect({
  label,
  description,
  value,
  options,
  onChange,
  disabled,
}: {
  label: string
  description: string
  value: string
  options: { value: string; label: string }[]
  onChange: (value: string) => void
  disabled?: boolean
}) {
  return (
    <div>
      <p className="text-sm font-medium text-[#e2e5eb]">{label}</p>
      <p className="text-xs text-[#848b9b] mt-0.5 mb-2">{description}</p>
      <select
        value={value}
        onChange={(e) => onChange(e.target.value)}
        disabled={disabled}
        className="w-full max-w-xs rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm text-[#e2e5eb] focus:border-[rgba(6,182,212,0.3)] focus:outline-none disabled:opacity-50"
      >
        {options.map((opt) => (
          <option key={opt.value} value={opt.value}>{opt.label}</option>
        ))}
      </select>
    </div>
  )
}

export default IntegrationsPage
