import React, { useEffect, useMemo, useState } from 'react'
import { applyFateToTest, d100, degrees, uid } from './rollHelpers'
import FateControls from './FateControls'

const CHARACTERISTIC_ALIASES = {
  WS: ['WS', 'Ws', 'ws'],
  BS: ['BS', 'Bs', 'bs'],
  S: ['S', 's'],
  T: ['T', 't'],
  Ag: ['Ag', 'AG', 'ag'],
  Int: ['Int', 'INT', 'int'],
  Per: ['Per', 'PER', 'per'],
  WP: ['WP', 'Wp', 'wp'],
  Wp: ['WP', 'Wp', 'wp'],
  Fel: ['Fel', 'FEL', 'fel'],
}

function characteristicFromSkillName(name) {
  const match = String(name || '').match(/\(([^)]+)\)/)
  const raw = match ? match[1].trim() : 'Int'
  if (/^wp$/i.test(raw)) return 'WP'
  if (/^ag$/i.test(raw)) return 'Ag'
  if (/^int$/i.test(raw)) return 'Int'
  if (/^per$/i.test(raw)) return 'Per'
  if (/^fel$/i.test(raw)) return 'Fel'
  if (/^bs$/i.test(raw)) return 'BS'
  if (/^ws$/i.test(raw)) return 'WS'
  if (/^s$/i.test(raw)) return 'S'
  if (/^t$/i.test(raw)) return 'T'
  return raw
}

function characteristicValue(chars, key, fallback = 45) {
  const aliases = CHARACTERISTIC_ALIASES[key] || [key]
  for (const alias of aliases) {
    if (typeof chars?.[alias] === 'number') return chars[alias]
  }
  return fallback
}

function skillTrainingBonus(skill) {
  if (skill?.plus20) return 20
  if (skill?.plus10) return 10
  if (skill?.trained) return 0
  return -20
}

function skillTrainingLabel(skill) {
  if (skill?.plus20) return 'Trained +20'
  if (skill?.plus10) return 'Trained +10'
  if (skill?.trained) return 'Trained'
  return 'Untrained -20'
}

// Deathwatch Basic Skills (may be attempted untrained at -20). Every other skill
// is Advanced and cannot be used untrained — the app still permits a manual
// Target override for GM rulings. List mirrors the rules database classification.
const BASIC_SKILLS = new Set([
  'awareness', 'carouse', 'charm', 'climb', 'command', 'concealment',
  'contortionist', 'deceive', 'dodge', 'evaluate', 'gamble', 'inquiry',
  'intimidate', 'logic', 'scrutiny', 'search', 'silent move', 'swim',
])

function skillBaseName(name) {
  return String(name || '').replace(/\([^)]*\)/g, '').trim().toLowerCase()
}

function isAdvancedSkill(name) {
  if (!name) return false
  return !BASIC_SKILLS.has(skillBaseName(name))
}

function isSkillUntrained(skill) {
  return !(skill?.trained || skill?.plus10 || skill?.plus20)
}

export default function SkillRoller({ playerSkills, playerCharacteristics, onResult, onReplaceResult, fate, spendFate, setError, setInfo }) {
  const [skillRollName, setSkillRollName] = useState('')
  const [skillRollModifier, setSkillRollModifier] = useState(0)
  const [manualSkillRoll, setManualSkillRoll] = useState('')
  const [skillTargetOverride, setSkillTargetOverride] = useState('')
  const [lastResult, setLastResult] = useState(null)

  const skillOptions = useMemo(() => {
    return Object.keys(playerSkills || {}).sort((a, b) => {
      const at = playerSkills[a]?.trained ? 0 : 1
      const bt = playerSkills[b]?.trained ? 0 : 1
      return at - bt || a.localeCompare(b)
    })
  }, [playerSkills])

  // Preselect the first (best-trained) skill once the sheet loads.
  useEffect(() => {
    if (!skillRollName && skillOptions.length > 0) setSkillRollName(skillOptions[0])
  }, [skillOptions, skillRollName])

  const selectedSkill = playerSkills?.[skillRollName] || null
  const selectedSkillCharacteristic = characteristicFromSkillName(skillRollName)
  const selectedSkillBase = characteristicValue(playerCharacteristics, selectedSkillCharacteristic, 45)
  const selectedSkillTrainingBonus = skillTrainingBonus(selectedSkill)
  const selectedSkillTarget = Math.max(1, Math.min(100, selectedSkillBase + selectedSkillTrainingBonus + (Number(skillRollModifier) || 0)))
  const skillTargetOverrideNum = parseInt(String(skillTargetOverride).trim(), 10)
  const hasSkillTargetOverride = String(skillTargetOverride).trim() !== '' && Number.isFinite(skillTargetOverrideNum)
  const effectiveSkillTarget = hasSkillTargetOverride
    ? Math.max(1, Math.min(100, skillTargetOverrideNum))
    : selectedSkillTarget

  // Advanced Skills cannot be attempted untrained (unless a manual Target overrides).
  const selectedSkillIsAdvanced = skillRollName ? isAdvancedSkill(skillRollName) : false
  const selectedSkillUntrained = selectedSkill ? isSkillUntrained(selectedSkill) : true
  const blockedUntrainedAdvanced = !hasSkillTargetOverride && !!skillRollName && selectedSkillIsAdvanced && selectedSkillUntrained

  function rollSkillCheck() {
    setError('')
    setInfo('')
    if (!skillRollName && !hasSkillTargetOverride) {
      setError('Select a skill or enter a target number')
      return
    }
    if (blockedUntrainedAdvanced) {
      setError(`${skillRollName} is an Advanced Skill and cannot be used untrained — train it, or set a manual Target to override.`)
      return
    }
    let roll
    if (manualSkillRoll.trim()) {
      const parsed = parseInt(manualSkillRoll.trim(), 10)
      if (!Number.isFinite(parsed) || parsed < 1 || parsed > 100) {
        setError('Manual skill roll must be a number between 1-100')
        return
      }
      roll = parsed
    } else {
      roll = d100()
    }
    const label = skillRollName || `Target ${effectiveSkillTarget}`
    const dg = degrees(effectiveSkillTarget, roll)
    const res = {
      id: uid(),
      ts: Date.now(),
      rollKind: 'skill',
      skillName: label,
      characteristic: skillRollName ? selectedSkillCharacteristic : null,
      base: skillRollName ? selectedSkillBase : null,
      training: skillRollName ? skillTrainingLabel(selectedSkill) : null,
      modifier: Number(skillRollModifier) || 0,
      target: effectiveSkillTarget,
      targetOverride: hasSkillTargetOverride,
      attackRoll: roll,
      success: dg.success,
      dos: dg.dos,
      dof: dg.dof,
      using: skillRollName ? selectedSkillCharacteristic : null,
    }
    setLastResult(res)
    onResult(res)
    setInfo(`${label}: ${dg.success ? `Success (${dg.dos} DoS)` : `Fail (${dg.dof} DoF)`}`)
  }

  async function applyFate(action) {
    if (!lastResult) return
    const ok = await spendFate()
    if (!ok) { setError('No fate points remaining'); return }
    const next = applyFateToTest(lastResult, action)
    setLastResult(next)
    onReplaceResult(next)
    setInfo(`${next.skillName}: ${next.success ? `Success (${next.dos} DoS)` : `Fail (${next.dof} DoF)`} ✧ ${next.fate.join(', ')}`)
  }

  return (
    <div className="rounded-xl bg-slate-900 border border-slate-600 p-4 space-y-3">
      <div className="flex items-center justify-between gap-3">
        <div>
          <div className="font-semibold">Skill Check</div>
          <div className="text-xs opacity-70">Uses this player sheet's skills and characteristics.</div>
        </div>
        <button onClick={rollSkillCheck} disabled={(skillOptions.length === 0 && !hasSkillTargetOverride) || blockedUntrainedAdvanced} className="rounded-xl px-4 py-2 bg-emerald-700 hover:bg-emerald-600 disabled:opacity-40">Roll Skill</button>
      </div>
      <div className="grid grid-cols-1 md:grid-cols-5 gap-3 items-end">
        <div className="md:col-span-2">
          <label className="text-xs uppercase opacity-70">Skill</label>
          <select className="w-full rounded-xl border border-slate-600 bg-slate-800 px-3 py-2" value={skillRollName} onChange={e=>setSkillRollName(e.target.value)} disabled={skillOptions.length === 0}>
            {skillOptions.length === 0 && <option value="">No sheet skills loaded</option>}
            {skillOptions.map(skill => (
              <option key={skill} value={skill}>{skill} • {skillTrainingLabel(playerSkills[skill])}</option>
            ))}
          </select>
        </div>
        <div>
          <label className="text-xs uppercase opacity-70">Modifier</label>
          <input className="w-full rounded-xl border border-slate-600 bg-slate-800 px-3 py-2" type="number" value={skillRollModifier} onChange={e=>setSkillRollModifier(parseInt(e.target.value||'0', 10))} disabled={hasSkillTargetOverride} />
        </div>
        <div>
          <label className="text-xs uppercase opacity-70">Target</label>
          <input className="w-full rounded-xl border border-slate-600 bg-slate-800 px-3 py-2" type="number" min="1" max="100" placeholder="auto" value={skillTargetOverride} onChange={e=>setSkillTargetOverride(e.target.value)} />
        </div>
        <div>
          <label className="text-xs uppercase opacity-70">Manual d100</label>
          <input className="w-full rounded-xl border border-slate-600 bg-slate-800 px-3 py-2" type="number" min="1" max="100" placeholder="optional" value={manualSkillRoll} onChange={e=>setManualSkillRoll(e.target.value)} />
        </div>
      </div>
      <div className="text-sm opacity-85">
        Target <span className="font-semibold">{effectiveSkillTarget}</span>
        {hasSkillTargetOverride ? (
          <span> = manual target</span>
        ) : skillRollName && (
          <span> = {selectedSkillCharacteristic} {selectedSkillBase} {selectedSkillTrainingBonus >= 0 ? '+' : ''}{selectedSkillTrainingBonus} training {Number(skillRollModifier) ? `${Number(skillRollModifier) > 0 ? '+' : ''}${Number(skillRollModifier)} mod` : '+0 mod'}</span>
        )}
      </div>
      {blockedUntrainedAdvanced && (
        <div className="text-xs rounded-lg bg-amber-900/40 border border-amber-700/50 px-3 py-2 text-amber-200">
          <span className="font-semibold">{skillRollName}</span> is an Advanced Skill and can't be used untrained. Train the skill, or enter a manual Target to override (GM ruling).
        </div>
      )}
      <FateControls
        fate={fate}
        disabled={!lastResult}
        onReroll={()=>applyFate('reroll')}
        onPlus10={()=>applyFate('plus10')}
        onAddDos={()=>applyFate('dos')}
      />
    </div>
  )
}
