'use client'

import type { BrandAlignmentScoreResult } from '@actuate-media/cms-core/brand-voice'
import { BRAND_VOICE_CHANNEL_PRESETS } from '@actuate-media/cms-core/brand-voice'
import { Loader2, Wand2 } from 'lucide-react'
import { useId, useState } from 'react'
import { toast } from 'sonner'
import { fixBrandVoiceContent } from '../../../lib/brand-voice-client.js'

const INPUT_CLASS =
  'w-full rounded-md border border-border bg-input-background px-3 py-2 text-base text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-60'
const TEXTAREA_CLASS = `${INPUT_CLASS} min-h-[120px] resize-y`
const LABEL_CLASS = 'mb-1 block text-sm font-medium text-foreground'

function scoreTone(score: number): string {
  if (score >= 85) return 'text-success'
  if (score >= 65) return 'text-warning'
  return 'text-destructive'
}

export function BrandVoiceAlignmentPanel({
  disabled,
  onScore,
}: {
  disabled: boolean
  onScore: (input: { content: string; channel?: string }) => Promise<{
    ok: boolean
    result?: BrandAlignmentScoreResult
    error?: string
  }>
}) {
  const contentId = useId()
  const channelId = useId()
  const [content, setContent] = useState('')
  const [channel, setChannel] = useState('')
  const [loading, setLoading] = useState(false)
  const [fixing, setFixing] = useState(false)
  const [result, setResult] = useState<BrandAlignmentScoreResult | null>(null)
  const [error, setError] = useState<string | null>(null)

  async function runScore() {
    if (!content.trim()) return
    setLoading(true)
    setError(null)
    try {
      const res = await onScore({
        content: content.trim(),
        channel: channel || undefined,
      })
      if (!res.ok || !res.result) {
        setResult(null)
        setError(res.error ?? 'Could not score this copy.')
        return
      }
      setResult(res.result)
    } finally {
      setLoading(false)
    }
  }

  async function runFix() {
    if (!content.trim()) return
    setFixing(true)
    setError(null)
    try {
      const res = await fixBrandVoiceContent({
        content: content.trim(),
        channel: channel || undefined,
      })
      if (!res.ok || !res.result) {
        setError(res.error ?? 'Could not fix this copy.')
        return
      }
      setContent(res.result.text)
      setResult(res.result.afterScore)
      toast.success(
        res.result.usedAi
          ? 'Copy revised to match brand voice.'
          : 'Applied brand voice rule fixes.',
      )
    } finally {
      setFixing(false)
    }
  }

  return (
    <div className="border-border space-y-4 rounded-md border border-dashed p-4">
      <div>
        <h4 className="text-foreground text-base font-medium">Check alignment</h4>
        <p className="text-muted-foreground mt-1 text-sm">
          Paste draft copy to score it against your vocabulary rules, mechanics, and channel limits.
        </p>
      </div>

      <div className="grid gap-4 md:grid-cols-[1fr_220px]">
        <div>
          <label htmlFor={contentId} className={LABEL_CLASS}>
            Draft copy
          </label>
          <textarea
            id={contentId}
            value={content}
            disabled={disabled || loading}
            placeholder="Paste a headline, meta description, or paragraph to score."
            onChange={(e) => setContent(e.target.value)}
            className={TEXTAREA_CLASS}
          />
        </div>
        <div>
          <label htmlFor={channelId} className={LABEL_CLASS}>
            Channel (optional)
          </label>
          <select
            id={channelId}
            value={channel}
            disabled={disabled || loading}
            onChange={(e) => setChannel(e.target.value)}
            className={INPUT_CLASS}
          >
            <option value="">General</option>
            {BRAND_VOICE_CHANNEL_PRESETS.map((preset) => (
              <option key={preset.id} value={preset.id}>
                {preset.label}
              </option>
            ))}
          </select>
          <button
            type="button"
            onClick={runScore}
            disabled={disabled || loading || !content.trim()}
            className="bg-primary text-primary-foreground mt-3 inline-flex w-full items-center justify-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50"
          >
            {loading && <Loader2 size={16} className="animate-spin" aria-hidden="true" />}
            Score copy
          </button>
        </div>
      </div>

      {error && (
        <div
          role="alert"
          className="border-destructive/30 bg-destructive/10 text-destructive rounded-md border p-3 text-sm"
        >
          {error}
        </div>
      )}

      {result && (
        <div className="space-y-3" aria-live="polite">
          <div className="flex flex-wrap items-center gap-3">
            <p className={`text-2xl font-medium ${scoreTone(result.score)}`}>{result.score}/100</p>
            <p className="text-muted-foreground text-sm">
              {result.channel ? `Scored for ${result.channel.replace(/_/g, ' ')}` : 'General score'}
            </p>
            {result.score < 85 && (
              <button
                type="button"
                onClick={runFix}
                disabled={disabled || fixing || loading}
                className="border-border bg-card text-foreground hover:bg-accent inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm disabled:cursor-not-allowed disabled:opacity-50"
              >
                {fixing ? (
                  <Loader2 size={16} className="animate-spin" aria-hidden="true" />
                ) : (
                  <Wand2 size={16} aria-hidden="true" />
                )}
                Fix to match brand voice
              </button>
            )}
          </div>

          {result.issues.length > 0 && (
            <ul className="space-y-2">
              {result.issues.map((issue) => (
                <li
                  key={issue.id}
                  className="border-border bg-muted/30 rounded-md border px-3 py-2 text-sm"
                >
                  <p className="text-foreground">{issue.message}</p>
                  {issue.suggestion && (
                    <p className="text-muted-foreground mt-1">{issue.suggestion}</p>
                  )}
                </li>
              ))}
            </ul>
          )}

          {result.dimensions.length > 0 && (
            <div className="grid gap-2 sm:grid-cols-2">
              {result.dimensions.map((dimension) => (
                <div key={dimension.name} className="border-border rounded-md border px-3 py-2">
                  <div className="flex items-center justify-between gap-2">
                    <p className="text-foreground text-sm font-medium">{dimension.name}</p>
                    <p className={`text-sm ${scoreTone(dimension.score)}`}>{dimension.score}</p>
                  </div>
                  <p className="text-muted-foreground mt-1 text-sm">{dimension.feedback}</p>
                </div>
              ))}
            </div>
          )}
        </div>
      )}
    </div>
  )
}
