import { useState, useEffect, useRef } from 'react'
import { ArrowLeft, Loader2, Save, Scan, Trash2 } from 'lucide-react'
import { Input } from '@/components/ui/Input'
import { Textarea } from '@/components/ui/Textarea'
import { usePermissions } from '@/hooks/usePermissions'
import { scriptsApi } from '@/api'
import { ScriptBodyEditor } from './ScriptBodyEditor'
import { ParameterSchemaBuilder } from './ParameterSchemaBuilder'
import { detectParameterCandidates } from '@/lib/scriptParameterDetector'
import { ParameterDetectorStepper } from './ParameterDetectorStepper'
import type {
  ScriptTemplateDetail,
  ScriptCategoryResponse,
  ScriptParametersSchema,
  ScriptTemplateCreateRequest,
  ScriptTemplateUpdateRequest,
  ParameterCandidate,
  ScriptParameter,
} from '@/types'

interface Props {
  templateId: string | null // null = create mode
  onBack: () => void
  onSaved: () => void
}

interface FormState {
  name: string
  description: string
  use_case: string
  category_id: string
  complexity: 'beginner' | 'intermediate' | 'advanced'
  tags: string
  estimated_runtime: string
  requires_elevation: boolean
  requires_modules: string
  script_body: string
  parameters_schema: ScriptParametersSchema
}

const EMPTY_FORM: FormState = {
  name: '',
  description: '',
  use_case: '',
  category_id: '',
  complexity: 'beginner',
  tags: '',
  estimated_runtime: '',
  requires_elevation: false,
  requires_modules: '',
  script_body: '',
  parameters_schema: { parameters: [] },
}

export function ScriptTemplateEditor({ templateId, onBack, onSaved }: Props) {
  const [form, setForm] = useState<FormState>(EMPTY_FORM)
  const [categories, setCategories] = useState<ScriptCategoryResponse[]>([])
  const [isLoading, setIsLoading] = useState(!!templateId)
  const [isSaving, setIsSaving] = useState(false)
  const [saveError, setSaveError] = useState<string | null>(null)
  const [isDirty, setIsDirty] = useState(false)
  const [deleteConfirm, setDeleteConfirm] = useState(false)
  const [template, setTemplate] = useState<ScriptTemplateDetail | null>(null)
  const [detectedCandidates, setDetectedCandidates] = useState<ParameterCandidate[]>([])
  const [showStepper, setShowStepper] = useState(false)
  const [detectionSummary, setDetectionSummary] = useState<string | null>(null)
  const acceptingCandidateRef = useRef(false)

  const { canShareScriptTemplate } = usePermissions()

  // Dismiss stepper if user manually edits the script body during detection
  // (but NOT when handleAcceptCandidate programmatically updates script_body)
  const scriptBodyRef = form.script_body
  useEffect(() => {
    if (showStepper && !acceptingCandidateRef.current) {
      setShowStepper(false)
      setDetectedCandidates([])
    }
    acceptingCandidateRef.current = false
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [scriptBodyRef])

  // Load categories + template detail (if editing)
  useEffect(() => {
    const load = async () => {
      try {
        const cats = await scriptsApi.getCategories()
        setCategories(cats)

        if (templateId) {
          const detail = await scriptsApi.getTemplateDetail(templateId)
          setTemplate(detail)
          const schema = detail.parameters_schema as ScriptParametersSchema
          setForm({
            name: detail.name,
            description: detail.description ?? '',
            use_case: detail.use_case ?? '',
            category_id: detail.category_id,
            complexity: detail.complexity,
            tags: detail.tags.join(', '),
            estimated_runtime: detail.estimated_runtime ?? '',
            requires_elevation: detail.requires_elevation,
            requires_modules: detail.requires_modules.join(', '),
            script_body: detail.script_body,
            parameters_schema: schema ?? { parameters: [] },
          })
        } else if (cats.length > 0) {
          setForm(f => ({ ...f, category_id: cats[0].id }))
        }
      } catch {
        setSaveError('Failed to load data')
      } finally {
        setIsLoading(false)
      }
    }
    load()
  }, [templateId])

  const updateField = <K extends keyof FormState>(key: K, value: FormState[K]) => {
    setForm(f => ({ ...f, [key]: value }))
    setIsDirty(true)
  }

  const handleSave = async () => {
    if (!form.name.trim()) {
      setSaveError('Name is required')
      return
    }
    if (!form.script_body.trim()) {
      setSaveError('Script body is required')
      return
    }
    if (!form.category_id) {
      setSaveError('Category is required')
      return
    }

    setIsSaving(true)
    setSaveError(null)

    const tags = form.tags.split(',').map(t => t.trim()).filter(Boolean)
    const requires_modules = form.requires_modules.split(',').map(m => m.trim()).filter(Boolean)

    try {
      if (templateId) {
        const data: ScriptTemplateUpdateRequest = {
          name: form.name,
          description: form.description || null,
          use_case: form.use_case || null,
          script_body: form.script_body,
          parameters_schema: form.parameters_schema as unknown as ScriptParametersSchema,
          tags,
          complexity: form.complexity,
          estimated_runtime: form.estimated_runtime || null,
          requires_elevation: form.requires_elevation,
          requires_modules,
        }
        await scriptsApi.updateTemplate(templateId, data)
      } else {
        const data: ScriptTemplateCreateRequest = {
          category_id: form.category_id,
          name: form.name,
          description: form.description || null,
          use_case: form.use_case || null,
          script_body: form.script_body,
          parameters_schema: form.parameters_schema as unknown as ScriptParametersSchema,
          tags,
          complexity: form.complexity,
          estimated_runtime: form.estimated_runtime || null,
          requires_elevation: form.requires_elevation,
          requires_modules,
        }
        await scriptsApi.createTemplate(data)
      }
      setIsDirty(false)
      onSaved()
    } catch (err: unknown) {
      const axiosErr = err as { response?: { data?: { detail?: string } } }
      setSaveError(axiosErr.response?.data?.detail ?? 'Failed to save template')
    } finally {
      setIsSaving(false)
    }
  }

  const handleDelete = async () => {
    if (!templateId) return
    try {
      await scriptsApi.deleteTemplate(templateId)
      onSaved()
    } catch {
      setSaveError('Failed to delete template')
    }
  }

  const handleShare = async (shared: boolean) => {
    if (!templateId) return
    try {
      const updated = await scriptsApi.shareTemplate(templateId, shared)
      setTemplate(updated)
    } catch {
      setSaveError('Failed to update sharing')
    }
  }

  const handleBack = () => {
    if (isDirty && !confirm('You have unsaved changes. Leave anyway?')) return
    onBack()
  }

  const handleDetectParameters = () => {
    const candidates = detectParameterCandidates(form.script_body)
    if (candidates.length === 0) {
      setDetectionSummary('No parameter candidates detected in the script body.')
      setShowStepper(false)
      setTimeout(() => setDetectionSummary(null), 4000)
      return
    }
    setDetectedCandidates(candidates)
    setDetectionSummary(null)
    setShowStepper(true)
  }

  const handleAcceptCandidate = (
    candidate: ParameterCandidate,
    overrides: {
      key: string
      label: string
      type: ScriptParameter['type']
      sensitive: boolean
      required: boolean
      defaultValue: string | boolean | number | null
    }
  ) => {
    let updatedScript = form.script_body
    if (candidate.source === 'param_block') {
      const defaultMatch = candidate.matchedLine.match(/=\s*(.+?)(?:\s*,?\s*$)/)
      if (defaultMatch) {
        updatedScript = updatedScript.replace(
          candidate.matchedLine,
          candidate.matchedLine.replace(defaultMatch[1], `'{{${overrides.key}}}'`)
        )
      }
    } else {
      const assignMatch = candidate.matchedLine.match(/=\s*(.+)$/)
      if (assignMatch) {
        updatedScript = updatedScript.replace(
          candidate.matchedLine,
          candidate.matchedLine.replace(assignMatch[1], `'{{${overrides.key}}}'`)
        )
      }
    }

    const existingParams = form.parameters_schema.parameters
    const newParam: ScriptParameter = {
      key: overrides.key,
      label: overrides.label,
      type: overrides.type,
      required: overrides.required,
      placeholder: null,
      group: null,
      order: existingParams.length + 1,
      help_text: null,
      options: null,
      default: overrides.defaultValue,
      validation: null,
      sensitive: overrides.sensitive,
    }

    acceptingCandidateRef.current = true
    setForm(f => ({
      ...f,
      script_body: updatedScript,
      parameters_schema: {
        parameters: [...f.parameters_schema.parameters, newParam],
      },
    }))
    setIsDirty(true)
  }

  const handleSkipCandidate = () => {
    // Nothing to do — stepper advances internally
  }

  const handleDetectionFinish = (acceptedCount: number, totalCount: number) => {
    setShowStepper(false)
    setDetectedCandidates([])
    setDetectionSummary(
      acceptedCount === 0
        ? 'No parameters were added.'
        : `Added ${acceptedCount} of ${totalCount} detected parameter${totalCount !== 1 ? 's' : ''}.`
    )
    setTimeout(() => setDetectionSummary(null), 5000)
  }

  if (isLoading) {
    return (
      <div className="flex items-center justify-center py-20">
        <Loader2 size={28} className="text-primary animate-spin" />
      </div>
    )
  }

  return (
    <div className="flex flex-col gap-6 pb-24">
      {/* Back link */}
      <button
        type="button"
        onClick={handleBack}
        className="flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors w-fit"
      >
        <ArrowLeft size={12} />
        Back to templates
      </button>

      <h1 className="text-2xl font-heading font-bold text-foreground">
        {templateId ? 'Edit Template' : 'New Template'}
      </h1>

      {/* ── Metadata ──────────────────────────────────────────────── */}
      <section className="card-flat p-5 space-y-4">
        <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">Metadata</p>

        <div>
          <label className="text-sm font-medium text-foreground mb-1 block">
            Name <span className="text-red-400">*</span>
          </label>
          <Input
            value={form.name}
            onChange={e => updateField('name', e.target.value)}
            placeholder="e.g. Create AD User"
          />
        </div>

        <div className="grid grid-cols-2 gap-4">
          <div>
            <label className="text-sm font-medium text-foreground mb-1 block">Description</label>
            <Textarea
              value={form.description}
              onChange={e => updateField('description', e.target.value)}
              placeholder="What does this script do?"
              rows={3}
            />
          </div>
          <div>
            <label className="text-sm font-medium text-foreground mb-1 block">Use Case</label>
            <Textarea
              value={form.use_case}
              onChange={e => updateField('use_case', e.target.value)}
              placeholder="When would you use this?"
              rows={3}
            />
          </div>
        </div>

        <div className="grid grid-cols-3 gap-4">
          <div>
            <label className="text-sm font-medium text-foreground mb-1 block">
              Category <span className="text-red-400">*</span>
            </label>
            <select
              value={form.category_id}
              onChange={e => updateField('category_id', e.target.value)}
              className="w-full rounded-lg border border-border bg-card text-foreground px-3 py-2 text-sm focus:outline-none focus:border-[rgba(96,165,250,0.3)]"
            >
              <option value="">Select category…</option>
              {categories.map(c => (
                <option key={c.id} value={c.id}>{c.name}</option>
              ))}
            </select>
          </div>
          <div>
            <label className="text-sm font-medium text-foreground mb-1 block">Complexity</label>
            <select
              value={form.complexity}
              onChange={e => updateField('complexity', e.target.value as FormState['complexity'])}
              className="w-full rounded-lg border border-border bg-card text-foreground px-3 py-2 text-sm focus:outline-none focus:border-[rgba(96,165,250,0.3)]"
            >
              <option value="beginner">Beginner</option>
              <option value="intermediate">Intermediate</option>
              <option value="advanced">Advanced</option>
            </select>
          </div>
          <div>
            <label className="text-sm font-medium text-foreground mb-1 block">Estimated Runtime</label>
            <Input
              value={form.estimated_runtime}
              onChange={e => updateField('estimated_runtime', e.target.value)}
              placeholder="e.g. 30 seconds"
            />
          </div>
        </div>

        <div className="grid grid-cols-2 gap-4">
          <div>
            <label className="text-sm font-medium text-foreground mb-1 block">Tags (comma-separated)</label>
            <Input
              value={form.tags}
              onChange={e => updateField('tags', e.target.value)}
              placeholder="active-directory, user, onboarding"
            />
          </div>
          <div>
            <label className="text-sm font-medium text-foreground mb-1 block">Required Modules (comma-separated)</label>
            <Input
              value={form.requires_modules}
              onChange={e => updateField('requires_modules', e.target.value)}
              placeholder="ActiveDirectory, GroupPolicy"
            />
          </div>
        </div>

        <div className="flex items-center gap-6">
          <label className="flex items-center gap-2 text-sm text-foreground">
            <input
              type="checkbox"
              checked={form.requires_elevation}
              onChange={e => updateField('requires_elevation', e.target.checked)}
              className="rounded border-border"
            />
            Requires elevation (Run as Administrator)
          </label>

          {/* Share toggle — only for owners/admins editing an existing template */}
          {templateId && template && canShareScriptTemplate && (
            <label className="flex items-center gap-2 text-sm text-foreground">
              <input
                type="checkbox"
                checked={template.team_id !== null}
                onChange={e => handleShare(e.target.checked)}
                className="rounded border-border"
              />
              Share with team
              <span className="text-xs text-muted-foreground">(visible to all team members)</span>
            </label>
          )}
        </div>
      </section>

      {/* ── Script Body ───────────────────────────────────────────── */}
      <section className="card-flat p-5 space-y-3">
        <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
          Script Body <span className="text-red-400">*</span>
        </p>
        <p className="text-xs text-muted-foreground">
          Use <code className="font-sans text-xs text-amber-400">{'{{param_key}}'}</code> for parameter placeholders.
          Supports <code className="font-sans text-xs text-amber-400">{'{% if param %} ... {% endif %}'}</code> conditionals
          and filters like <code className="font-sans text-xs text-amber-400">{'{{ param | as_secure_string }}'}</code>.
        </p>
        <ScriptBodyEditor
          value={form.script_body}
          onChange={v => updateField('script_body', v)}
        />

        {/* Detect Parameters button + stepper */}
        {form.script_body.trim() && !showStepper && (
          <button
            type="button"
            onClick={handleDetectParameters}
            className="flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] hover:border-[rgba(255,255,255,0.12)] px-3 py-1.5 rounded-lg transition-all"
          >
            <Scan size={14} />
            Detect Parameters
          </button>
        )}

        {detectionSummary && (
          <p className="text-xs text-muted-foreground italic">{detectionSummary}</p>
        )}

        {showStepper && detectedCandidates.length > 0 && (
          <ParameterDetectorStepper
            candidates={detectedCandidates}
            existingKeys={form.parameters_schema.parameters.map(p => p.key)}
            onAccept={handleAcceptCandidate}
            onSkip={handleSkipCandidate}
            onFinish={handleDetectionFinish}
          />
        )}
      </section>

      {/* ── Parameters Schema ─────────────────────────────────────── */}
      <section className="card-flat p-5 space-y-3">
        <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">Parameters</p>
        <p className="text-xs text-muted-foreground">
          Define form fields that users fill in when generating a script. Each parameter maps to a <code className="font-sans text-xs text-amber-400">{'{{key}}'}</code> placeholder in the script body.
        </p>
        <ParameterSchemaBuilder
          schema={form.parameters_schema}
          onChange={v => updateField('parameters_schema', v)}
        />
      </section>

      {/* ── Fixed Action Bar ──────────────────────────────────────── */}
      <div className="fixed bottom-0 left-0 right-0 z-20 border-t border-border bg-background/80 px-6 py-3">
        <div className="max-w-5xl mx-auto flex items-center justify-between">
          <div className="flex items-center gap-3">
            <button
              type="button"
              onClick={handleSave}
              disabled={isSaving}
              className="flex items-center gap-1.5 bg-primary text-white font-semibold text-sm px-5 py-2 rounded-lg hover:brightness-110 active:scale-[0.98] transition-all disabled:opacity-50 disabled:cursor-not-allowed"
            >
              {isSaving ? <Loader2 size={14} className="animate-spin" /> : <Save size={14} />}
              {templateId ? 'Save Changes' : 'Create Template'}
            </button>
            <button
              type="button"
              onClick={handleBack}
              className="text-sm text-muted-foreground hover:text-foreground transition-colors px-4 py-2"
            >
              Cancel
            </button>
          </div>

          {templateId && (
            deleteConfirm ? (
              <div className="flex items-center gap-2">
                <span className="text-xs text-rose-500">Delete this template?</span>
                <button
                  type="button"
                  onClick={handleDelete}
                  className="text-xs font-sans text-xs text-rose-500 hover:text-rose-400 px-2 py-1"
                >
                  Confirm
                </button>
                <button
                  type="button"
                  onClick={() => setDeleteConfirm(false)}
                  className="text-xs font-sans text-xs text-muted-foreground hover:text-foreground px-2 py-1"
                >
                  Cancel
                </button>
              </div>
            ) : (
              <button
                type="button"
                onClick={() => setDeleteConfirm(true)}
                className="flex items-center gap-1.5 text-sm text-rose-500 hover:text-rose-400 transition-colors px-3 py-2"
              >
                <Trash2 size={14} />
                Delete
              </button>
            )
          )}
        </div>
      </div>

      {/* Save error */}
      {saveError && (
        <p className="text-sm text-rose-500 text-center">{saveError}</p>
      )}
    </div>
  )
}
