import RefreshIcon from '@mui/icons-material/Refresh';
import {
  Box,
  FormControl,
  IconButton,
  Input,
  InputLabel,
  MenuItem,
  Paper,
  Select,
  Slider,
  Tooltip,
  Typography,
} from '@mui/material';
import Grid from '@mui/material/Unstable_Grid2/Grid2';
import { useState } from 'react';

import type { LineState, ModelInfo } from './EditorContainer';
import { defaultLineState } from './EditorContainer';

interface InputSliderProps {
  value: number;
  setValue: (value: number) => void;
  step: number;
  min: number;
  max: number;
  label: string;
}

function InputSlider({
  value,
  setValue,
  step,
  min,
  max,
  label,
}: InputSliderProps) {
  const handleSliderChange = (event: Event, newValue: number | number[]) => {
    setValue(newValue as number);
  };

  const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setValue(event.target.value === '' ? 0 : Number(event.target.value));
  };

  const handleBlur = () => {
    if (value < min) {
      setValue(min);
    } else if (value > max) {
      setValue(max);
    }
  };

  return (
    <Box>
      <Grid
        container
        spacing={2}
        alignItems='center'
        justifyContent='space-between'
      >
        <Grid xs={9}>
          <Typography id='input-slider' gutterBottom>
            {label}
          </Typography>
          <Slider
            value={typeof value === 'number' ? value : min}
            onChange={handleSliderChange}
            aria-labelledby='input-slider'
            step={step}
            min={min}
            max={max}
          />
        </Grid>
        <Grid xs={3}>
          <Input
            value={value}
            onChange={handleInputChange}
            onBlur={handleBlur}
            inputProps={{
              step,
              min,
              max,
              type: 'number',
            }}
          />
        </Grid>
      </Grid>
    </Box>
  );
}

interface LineSettingProps {
  modelList: ModelInfo[];
  lines: LineState[];
  setLines: (lines: LineState[]) => void;
  currentIndex: number;
}

export default function LineSetting({
  modelList,
  lines,
  setLines,
  currentIndex,
}: LineSettingProps) {
  const [styleWeightUB, setStyleWeightUB] = useState(10);

  const setLineState = (newState: Partial<LineState>) => {
    const newLines = lines.map((line, index) => {
      if (index === currentIndex) {
        return {
          ...line,
          ...newState,
        };
      }
      return line;
    });
    setLines(newLines);
  };

  const handleModelChange = (model: string) => {
    const selected = modelList?.find((m) => m.name === model);
    setLineState({
      model,
      modelFile: selected?.files[0] || '',
      style: selected?.styles[0] || '',
      speaker: selected?.speakers?.[0] || '',
    });
  };

  const handleDefault = () => {
    setLineState({
      ...defaultLineState,
      model: lines[currentIndex].model,
      modelFile: lines[currentIndex].modelFile,
      text: lines[currentIndex].text,
      speaker: lines[currentIndex].speaker,
      //もし選択肢にNeutralがあればそれを選択、あるはずだが一応
      style: modelList
        .find((model) => model.name === lines[currentIndex].model)
        ?.styles.includes('Neutral')
        ? 'Neutral'
        : modelList.find((model) => model.name === lines[currentIndex].model)
            ?.styles[0] || '',
    });
  };

  return (
    <Paper sx={{ p: 2 }}>
      <Box
        sx={{
          display: 'flex',
          justifyContent: 'space-between',
          mb: 1,
          alignItems: 'center',
        }}
      >
        <Typography>テキスト{currentIndex + 1}の設定</Typography>
        <Tooltip title='デフォルト設定に戻す' placement='left'>
          <IconButton onClick={handleDefault}>
            <RefreshIcon />
          </IconButton>
        </Tooltip>
      </Box>
      {/* Model Image Display */}
      <Box sx={{ mb: 2, display: 'flex', justifyContent: 'center' }}>
        <img
          src={`/images/${lines[currentIndex].model}.png`}
          alt={lines[currentIndex].model}
          style={{
            width: '250px',
            height: '250px',
            objectFit: 'cover',
            borderRadius: '12px',
            border: '1px solid rgba(0, 0, 0, 0.12)',
          }}
          onError={(e) => {
            // Hide image if it doesn't exist
            (e.target as HTMLImageElement).style.display = 'none';
          }}
        />
      </Box>
      <FormControl fullWidth variant='standard' sx={{ mb: 1, minWidth: 120 }}>
        <InputLabel>モデル</InputLabel>
        <Select
          value={lines[currentIndex].model}
          onChange={(e) => handleModelChange(e.target.value as string)}
        >
          {modelList.map((modelInfo, index) => (
            <MenuItem key={index} value={modelInfo.name}>
              {modelInfo.name}
            </MenuItem>
          ))}
        </Select>
      </FormControl>
      <FormControl fullWidth variant='standard' sx={{ mb: 1, minWidth: 120 }}>
        <InputLabel>モデルファイル</InputLabel>
        <Select
          value={lines[currentIndex].modelFile}
          onChange={(e) =>
            setLineState({ modelFile: e.target.value as string })
          }
        >
          {modelList
            .find((speaker) => speaker.name === lines[currentIndex].model)
            ?.files.map((file, index) => (
              <MenuItem key={index} value={file}>
                {file}
              </MenuItem>
            ))}
        </Select>
      </FormControl>
      <FormControl fullWidth variant='standard' sx={{ mb: 1, minWidth: 120 }}>
        <InputLabel>話者</InputLabel>
        <Select
          value={lines[currentIndex].speaker}
          onChange={(e) => setLineState({ speaker: e.target.value as string })}
        >
          {modelList
            .find((model) => model.name === lines[currentIndex].model)
            ?.speakers?.map((model, index) => (
              <MenuItem key={index} value={model}>
                {model}
              </MenuItem>
            ))}
        </Select>
      </FormControl>
      <FormControl fullWidth variant='standard' sx={{ mb: 2, minWidth: 120 }}>
        <InputLabel>スタイル</InputLabel>
        <Select
          value={lines[currentIndex].style}
          onChange={(e) => setLineState({ style: e.target.value as string })}
        >
          {modelList
            .find((speaker) => speaker.name === lines[currentIndex].model)
            ?.styles.map((style, index) => (
              <MenuItem key={index} value={style}>
                {style}
              </MenuItem>
            ))}
        </Select>
      </FormControl>
      <InputSlider
        label='スタイルの強さ上限設定'
        value={styleWeightUB}
        setValue={(value) => setStyleWeightUB(value)}
        step={0.1}
        min={1}
        max={20}
      />
      <InputSlider
        label='スタイルの強さ（崩壊したら下げて）'
        value={lines[currentIndex].styleWeight}
        setValue={(value) => setLineState({ styleWeight: value })}
        step={0.1}
        min={0}
        max={styleWeightUB}
      />
      <InputSlider
        label='話速'
        value={lines[currentIndex].speed}
        setValue={(value) => setLineState({ speed: value })}
        step={0.05}
        min={0.5}
        max={2}
      />
      <InputSlider
        label='テンポの緩急'
        value={lines[currentIndex].sdpRatio}
        setValue={(value) => setLineState({ sdpRatio: value })}
        step={0.05}
        min={0}
        max={1}
      />
      <InputSlider
        label='Noise'
        value={lines[currentIndex].noise}
        setValue={(value) => setLineState({ noise: value })}
        step={0.05}
        min={0}
        max={1}
      />
      <InputSlider
        label='NoiseW'
        value={lines[currentIndex].noisew}
        setValue={(value) => setLineState({ noisew: value })}
        step={0.05}
        min={0}
        max={1}
      />
      <InputSlider
        label='音高(1以外では音質劣化)'
        value={lines[currentIndex].pitchScale}
        setValue={(value) => setLineState({ pitchScale: value })}
        step={0.05}
        min={0.7}
        max={1.3}
      />
      <InputSlider
        label='抑揚(1以外では音質劣化)'
        value={lines[currentIndex].intonationScale}
        setValue={(value) => setLineState({ intonationScale: value })}
        step={0.05}
        min={0.7}
        max={1.3}
      />
      <InputSlider
        label='次のテキストとの間の無音'
        value={lines[currentIndex].silenceAfter}
        setValue={(value) => setLineState({ silenceAfter: value })}
        step={0.05}
        min={0}
        max={1.5}
      />
    </Paper>
  );
}
