import {
  mdiAlbum,
  mdiAlertCircleOutline,
  mdiChartTimelineVariant,
  mdiCheckCircleOutline,
  mdiChevronRight,
  mdiClockOutline,
  mdiInformationOutline,
  mdiExportVariant,
  mdiMicrophone,
  mdiMusic,
  mdiOpenInNew,
  mdiRobot,
  mdiTuneVariant,
  mdiWaveform,
} from '@mdi/js';
import axios from 'axios';
import Head from 'next/head';
import Link from 'next/link';
import React, { DragEvent, ReactElement, useEffect, useMemo, useRef, useState } from 'react';
import AudioWaveformPreview from '../components/Studio/AudioWaveformPreview';
import BaseButton from '../components/BaseButton';
import BaseIcon from '../components/BaseIcon';
import CardBox from '../components/CardBox';
import FormField from '../components/FormField';
import NotificationBar from '../components/NotificationBar';
import SectionMain from '../components/SectionMain';
import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton';
import { getPageTitle } from '../config';
import { hasPermission } from '../helpers/userPermissions';
import LayoutAuthenticated from '../layouts/Authenticated';
import FileUploader from '../components/Uploaders/UploadService';
import { useAppSelector } from '../stores/hooks';

type GenreOption = {
  id: string;
  name: string;
  description?: string;
  typical_bpm_min?: number;
  typical_bpm_max?: number;
};

type LanguageOption = {
  id: string;
  name: string;
  iso_code?: string;
};

type MasteringPresetOption = {
  id: string;
  name: string;
  target: string;
  lufs_target?: number;
  true_peak_db?: number;
};

type AiModelOption = {
  id: string;
  name: string;
  model_type: string;
  provider?: string;
  version?: string;
};

type RecentSession = {
  id: string;
  name: string;
  status: string;
  mood?: string;
  target_bpm?: number;
  target_key?: string;
  updatedAt: string;
  genre?: {
    id: string;
    name: string;
  } | null;
  projectHref: string;
  song?: {
    id: string;
    title: string;
    href: string;
  } | null;
  generationRequest?: {
    id: string;
    status: string;
    request_type: string;
    href: string;
  } | null;
  mixSession?: {
    id: string;
    status: string;
    href: string;
  } | null;
  masteringSession?: {
    id: string;
    status: string;
    href: string;
  } | null;
  exportJob?: {
    id: string;
    status: string;
    format: string;
    href: string;
  } | null;
};

type UploadedFile = {
  id?: string;
  name: string;
  sizeInBytes?: number;
  privateUrl: string;
  publicUrl: string;
  new: boolean;
};

type CreatedLink = {
  id: string;
  href: string;
  status?: string;
  format?: string;
  title?: string;
  name?: string;
  fileName?: string;
  publicUrl?: string;
  bpm?: number;
  key_signature?: string;
  mood?: string;
  request_type?: string;
  distribution_status?: string;
  isrc?: string;
};

type CreatedSession = {
  project: CreatedLink & { name?: string };
  song: CreatedLink;
  generationRequest: CreatedLink;
  recordingSession?: CreatedLink | null;
  vocalAsset?: CreatedLink | null;
  mixSession: CreatedLink;
  masteringSession: CreatedLink;
  exportJob: CreatedLink;
  songMetadata: CreatedLink;
  coverArtwork: CreatedLink;
  arrangementSections: Array<{
    id: string;
    label: string;
    section_type: string;
    start_bar: number;
    bar_length: number;
  }>;
  tracks: Array<{
    id: string;
    name: string;
    track_type: string;
    instrument: string;
  }>;
};

type LaunchpadResponse = {
  genres: GenreOption[];
  languages: LanguageOption[];
  masteringPresets: MasteringPresetOption[];
  aiModels: AiModelOption[];
  recentSessions: RecentSession[];
};

type DetectedVocalAnalysis = {
  bpm?: number;
  bpmConfidence?: number;
  key?: string;
  keyConfidence?: number;
  overallConfidence?: number;
};

type SubmittedVocalPreview = {
  file?: File | null;
  audioUrl?: string;
  name: string;
  sizeInBytes?: number;
  analysis?: DetectedVocalAnalysis | null;
};

type FormState = {
  title: string;
  genreId: string;
  languageId: string;
  mood: string;
  targetBpm: string;
  targetKey: string;
  vocalMode: 'instrumental' | 'upload' | 'record';
  promptText: string;
  notes: string;
  masteringPresetId: string;
  exportFormat: 'wav' | 'mp3' | 'stems_zip';
  includeStems: boolean;
};

const initialForm: FormState = {
  title: '',
  genreId: '',
  languageId: '',
  mood: 'energetic',
  targetBpm: '',
  targetKey: '',
  vocalMode: 'upload',
  promptText: '',
  notes: '',
  masteringPresetId: '',
  exportFormat: 'wav',
  includeStems: true,
};

const moodOptions = ['happy', 'sad', 'spiritual', 'energetic', 'romantic', 'chill', 'aggressive'];
const vocalModes: Array<{ value: FormState['vocalMode']; title: string; description: string }> = [
  {
    value: 'upload',
    title: 'Upload vocal',
    description: 'Prepare a beat around an imported vocal take and queue vocal treatment.',
  },
  {
    value: 'record',
    title: 'Record later',
    description: 'Start with an instrumental draft and a planned recording session.',
  },
  {
    value: 'instrumental',
    title: 'Instrumental only',
    description: 'Build a beat-first session without a vocal chain yet.',
  },
];

const vocalUploadSchema = {
  size: 20 * 1024 * 1024,
  formats: ['mp3', 'wav'],
};

const stageCards = [
  {
    label: 'Beat generation',
    detail: 'Queue a South African genre-aware instrumental brief.',
    icon: mdiRobot,
  },
  {
    label: 'Vocal workflow',
    detail: 'Prepare upload or recording steps with language-aware context.',
    icon: mdiMicrophone,
  },
  {
    label: 'Auto mix & master',
    detail: 'Stage mix, mastering, metadata, artwork, and export in one go.',
    icon: mdiTuneVariant,
  },
];

const NOTE_NAMES = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'];
const MAJOR_PROFILE = [6.35, 2.23, 3.48, 2.33, 4.38, 4.09, 2.52, 5.19, 2.39, 3.66, 2.29, 2.88];
const MINOR_PROFILE = [6.33, 2.68, 3.52, 5.38, 2.6, 3.53, 2.54, 4.75, 3.98, 2.69, 3.34, 3.17];

function formatFileSize(sizeInBytes?: number) {
  if (!sizeInBytes) {
    return '';
  }

  const sizeInKb = sizeInBytes / 1024;

  if (sizeInKb < 1024) {
    return `${Math.max(1, Math.round(sizeInKb))} KB`;
  }

  return `${(sizeInKb / 1024).toFixed(1)} MB`;
}

function normalizeTempo(value: number) {
  let bpm = value;

  while (bpm < 70) {
    bpm *= 2;
  }

  while (bpm > 180) {
    bpm /= 2;
  }

  return Math.round(bpm);
}

function normalizeConfidence(value?: number) {
  if (typeof value !== 'number' || Number.isNaN(value)) {
    return 0;
  }

  return Math.min(1, Math.max(0, value));
}

function getConfidenceLabel(value?: number) {
  const confidence = normalizeConfidence(value);

  if (confidence >= 0.78) {
    return 'High';
  }

  if (confidence >= 0.5) {
    return 'Medium';
  }

  return 'Low';
}

function getConfidenceClasses(value?: number) {
  const confidence = normalizeConfidence(value);

  if (confidence >= 0.78) {
    return 'border-emerald-300/30 bg-emerald-500/10 text-emerald-100';
  }

  if (confidence >= 0.5) {
    return 'border-amber-300/30 bg-amber-500/10 text-amber-100';
  }

  return 'border-rose-300/30 bg-rose-500/10 text-rose-100';
}

function formatConfidenceValue(value?: number) {
  const confidence = normalizeConfidence(value);

  if (!confidence) {
    return '';
  }

  return `${Math.round(confidence * 100)}%`;
}

function formatConfidenceSummary(value?: number) {
  const percentage = formatConfidenceValue(value);

  if (!percentage) {
    return '';
  }

  return `${getConfidenceLabel(value)} confidence · ${percentage}`;
}

function getConfidenceTooltip(metricLabel: string, value?: number) {
  const label = getConfidenceLabel(value);
  const percentage = formatConfidenceValue(value);
  const summary = percentage
    ? `${metricLabel} is currently ${label.toLowerCase()} confidence (${percentage}).`
    : `${metricLabel} confidence is currently unavailable.`;

  if (label === 'High') {
    return `${summary} High means the vocal signal looked stable and the detector found a strong match.`;
  }

  if (label === 'Medium') {
    return `${summary} Medium means the suggestion is usable, but you should still confirm it by ear.`;
  }

  return `${summary} Low means the take looks noisy, sparse, or ambiguous, so you should verify it manually.`;
}

function hasLowConfidence(value?: number) {
  const confidence = normalizeConfidence(value);

  return confidence > 0 && confidence < 0.5;
}

function getLowConfidenceWarning(analysis?: DetectedVocalAnalysis | null, analysisError?: string) {
  if (analysisError) {
    return 'This vocal take uploaded successfully, but the signal looks noisy or ambiguous enough that automatic BPM/key detection could not lock in cleanly.';
  }

  if (!analysis) {
    return '';
  }

  if (hasLowConfidence(analysis.bpmConfidence) && hasLowConfidence(analysis.keyConfidence)) {
    return 'Low-confidence BPM and key results usually mean the vocal is noisy, sparse, or too free-form to match reliably. Double-check both by ear before launching.';
  }

  if (hasLowConfidence(analysis.bpmConfidence)) {
    return 'The BPM estimate is low confidence, which usually means the vocal rhythm is noisy or loosely phrased. Use tap tempo or set BPM manually before launching.';
  }

  if (hasLowConfidence(analysis.keyConfidence)) {
    return 'The key estimate is low confidence, which usually means the pitch center is unclear or the take is noisy. Treat the suggested key as a starting point and verify by ear.';
  }

  if (hasLowConfidence(analysis.overallConfidence)) {
    return 'Overall analysis confidence is low, so the uploaded take may be too noisy or ambiguous for strong automatic matching. Review the suggestions carefully.';
  }

  return '';
}

function mixToMono(audioBuffer: AudioBuffer) {
  const mixed = new Float32Array(audioBuffer.length);

  for (let channelIndex = 0; channelIndex < audioBuffer.numberOfChannels; channelIndex += 1) {
    const channelData = audioBuffer.getChannelData(channelIndex);

    for (let sampleIndex = 0; sampleIndex < audioBuffer.length; sampleIndex += 1) {
      mixed[sampleIndex] += channelData[sampleIndex] / audioBuffer.numberOfChannels;
    }
  }

  return mixed;
}

function downSampleBuffer(samples: Float32Array, sampleRate: number, targetRate = 22050) {
  if (sampleRate <= targetRate) {
    return { sampleRate, samples };
  }

  const ratio = sampleRate / targetRate;
  const newLength = Math.max(1, Math.round(samples.length / ratio));
  const downSampled = new Float32Array(newLength);

  for (let index = 0; index < newLength; index += 1) {
    const start = Math.floor(index * ratio);
    const end = Math.min(samples.length, Math.floor((index + 1) * ratio));
    let sum = 0;

    for (let sampleIndex = start; sampleIndex < end; sampleIndex += 1) {
      sum += samples[sampleIndex];
    }

    downSampled[index] = end > start ? sum / (end - start) : samples[start] || 0;
  }

  return { sampleRate: targetRate, samples: downSampled };
}

function estimateTempo(samples: Float32Array, sampleRate: number) {
  const windowSizes = [1024, 2048, 4096];
  const aggregatedScores = new Map<number, number>();
  let totalPeaks = 0;

  windowSizes.forEach((windowSize, windowIndex) => {
    const energies: number[] = [];

    for (let start = 0; start + windowSize < samples.length; start += windowSize) {
      let sum = 0;

      for (let sampleIndex = start; sampleIndex < start + windowSize; sampleIndex += 1) {
        sum += Math.abs(samples[sampleIndex]);
      }

      energies.push(sum / windowSize);
    }

    if (energies.length < 8) {
      return;
    }

    const meanEnergy = energies.reduce((total, value) => total + value, 0) / energies.length;
    const variance = energies.reduce((total, value) => total + (value - meanEnergy) ** 2, 0) / energies.length;
    const threshold = meanEnergy + Math.sqrt(variance) * (0.22 + windowIndex * 0.08);
    const peaks: number[] = [];

    for (let index = 1; index < energies.length - 1; index += 1) {
      if (energies[index] > threshold && energies[index] >= energies[index - 1] && energies[index] >= energies[index + 1]) {
        if (!peaks.length || index - peaks[peaks.length - 1] > 1 + windowIndex) {
          peaks.push(index);
        }
      }
    }

    if (peaks.length < 2) {
      return;
    }

    totalPeaks += peaks.length;
    const windowWeight = 1.2 - windowIndex * 0.2;

    peaks.forEach((peak, peakIndex) => {
      for (let offset = 1; offset <= 8 && peakIndex + offset < peaks.length; offset += 1) {
        const interval = peaks[peakIndex + offset] - peak;

        if (!interval) {
          continue;
        }

        const bpm = normalizeTempo((60 * sampleRate) / (interval * windowSize));
        const intervalWeight = windowWeight / offset;
        aggregatedScores.set(bpm, (aggregatedScores.get(bpm) || 0) + intervalWeight);
      }
    });
  });

  if (!aggregatedScores.size) {
    return null;
  }

  const smoothedScores = new Map<number, number>();
  Array.from(aggregatedScores.entries()).forEach(([bpm, score]) => {
    let smoothedScore = score;

    for (let neighbor = bpm - 2; neighbor <= bpm + 2; neighbor += 1) {
      if (neighbor === bpm) {
        continue;
      }

      const neighborScore = aggregatedScores.get(neighbor);

      if (neighborScore) {
        smoothedScore += neighborScore * (neighbor === bpm - 1 || neighbor === bpm + 1 ? 0.55 : 0.25);
      }
    }

    smoothedScores.set(bpm, smoothedScore);
  });

  const rankedTempos = Array.from(smoothedScores.entries()).sort((left, right) => right[1] - left[1]);
  const [bestEntry, secondEntry] = rankedTempos;

  if (!bestEntry) {
    return null;
  }

  const [bpm, bestScore] = bestEntry;
  const secondScore = secondEntry?.[1] || 0;
  const totalScore = rankedTempos.reduce((total, [, score]) => total + score, 0);
  const dominance = totalScore ? bestScore / totalScore : 0;
  const separation = bestScore ? (bestScore - secondScore) / bestScore : 0;
  const peakCoverage = Math.min(1, totalPeaks / 28);
  const confidence = normalizeConfidence(dominance * 0.45 + separation * 0.4 + peakCoverage * 0.15);

  return { bpm, confidence };
}

function estimateDominantPitch(segment: Float32Array, sampleRate: number) {
  let rms = 0;

  for (let index = 0; index < segment.length; index += 1) {
    rms += segment[index] * segment[index];
  }

  rms = Math.sqrt(rms / segment.length);

  if (rms < 0.012) {
    return null;
  }

  const minLag = Math.floor(sampleRate / 1000);
  const maxLag = Math.min(Math.floor(sampleRate / 80), segment.length - 1);
  let bestLag = -1;
  let bestCorrelation = 0;
  let secondCorrelation = 0;

  for (let lag = minLag; lag <= maxLag; lag += 1) {
    let correlation = 0;

    for (let index = 0; index + lag < segment.length; index += 1) {
      correlation += segment[index] * segment[index + lag];
    }

    const normalizedCorrelation = correlation / Math.max(1, segment.length - lag);

    if (normalizedCorrelation > bestCorrelation) {
      secondCorrelation = bestCorrelation;
      bestCorrelation = normalizedCorrelation;
      bestLag = lag;
    } else if (normalizedCorrelation > secondCorrelation) {
      secondCorrelation = normalizedCorrelation;
    }
  }

  if (bestLag <= 0 || bestCorrelation <= 0) {
    return null;
  }

  return {
    frequency: sampleRate / bestLag,
    rms,
    clarity: normalizeConfidence((bestCorrelation - secondCorrelation) / bestCorrelation),
  };
}

function scorePitchProfiles(histogram: number[], profile: number[]) {
  return NOTE_NAMES.map((_, tonicIndex) =>
    histogram.reduce((total, value, pitchIndex) => total + value * profile[(pitchIndex - tonicIndex + 12) % 12], 0),
  );
}

function estimateMusicalKey(samples: Float32Array, sampleRate: number) {
  const segmentSizes = [4096, 8192];
  const totalSegments = 24;
  const histogram = new Array(12).fill(0) as number[];
  let acceptedSegments = 0;
  let clarityTotal = 0;

  segmentSizes.forEach((segmentSize, segmentIndex) => {
    if (samples.length < segmentSize) {
      return;
    }

    const step = Math.max(1, Math.floor((samples.length - segmentSize) / totalSegments));

    for (let offset = 0; offset + segmentSize <= samples.length; offset += step) {
      const segment = samples.slice(offset, offset + segmentSize);
      const detectedPitch = estimateDominantPitch(segment, sampleRate);

      if (!detectedPitch || detectedPitch.frequency < 80 || detectedPitch.frequency > 1000) {
        continue;
      }

      const midi = Math.round(69 + 12 * Math.log2(detectedPitch.frequency / 440));
      const pitchClass = ((midi % 12) + 12) % 12;
      const segmentWeight = detectedPitch.rms * (0.75 + detectedPitch.clarity * 0.75) * (segmentIndex === 0 ? 1 : 0.85);

      histogram[pitchClass] += segmentWeight;
      acceptedSegments += 1;
      clarityTotal += detectedPitch.clarity;
    }
  });

  const histogramTotal = histogram.reduce((total, value) => total + value, 0);

  if (!histogramTotal || !acceptedSegments) {
    return null;
  }

  const normalizedHistogram = histogram.map((value) => value / histogramTotal);
  const majorScores = scorePitchProfiles(normalizedHistogram, MAJOR_PROFILE);
  const minorScores = scorePitchProfiles(normalizedHistogram, MINOR_PROFILE);
  const rankedScores = [
    ...majorScores.map((score, index) => ({ label: `${NOTE_NAMES[index]} major`, score })),
    ...minorScores.map((score, index) => ({ label: `${NOTE_NAMES[index]} minor`, score })),
  ].sort((left, right) => right.score - left.score);

  const bestMatch = rankedScores[0];
  const runnerUp = rankedScores[1];

  if (!bestMatch) {
    return null;
  }

  const margin = bestMatch.score ? (bestMatch.score - (runnerUp?.score || 0)) / bestMatch.score : 0;
  const segmentCoverage = Math.min(1, acceptedSegments / 16);
  const averageClarity = clarityTotal / acceptedSegments;
  const confidence = normalizeConfidence(margin * 0.55 + averageClarity * 0.3 + segmentCoverage * 0.15);

  return {
    key: bestMatch.label,
    confidence,
  };
}

async function detectVocalAnalysis(file: File): Promise<DetectedVocalAnalysis | null> {
  if (typeof window === 'undefined' || !window.AudioContext) {
    throw new Error('Audio analysis is unavailable in this browser.');
  }

  const audioBuffer = await file.arrayBuffer();
  const audioContext = new window.AudioContext();

  try {
    const decoded = await audioContext.decodeAudioData(audioBuffer.slice(0));
    const mono = mixToMono(decoded);
    const { sampleRate, samples } = downSampleBuffer(mono, decoded.sampleRate);
    const tempoMatch = estimateTempo(samples, sampleRate);
    const keyMatch = estimateMusicalKey(samples, sampleRate);
    const bpm = tempoMatch?.bpm;
    const bpmConfidence = tempoMatch?.confidence;
    const key = keyMatch?.key;
    const keyConfidence = keyMatch?.confidence;
    const confidenceValues = [bpmConfidence, keyConfidence].filter((value): value is number => typeof value === 'number');

    if (!bpm && !key) {
      return null;
    }

    const overallConfidence = normalizeConfidence(
      confidenceValues.reduce((total, value) => total + value, 0) / Math.max(1, confidenceValues.length),
    );

    return { bpm, bpmConfidence, key, keyConfidence, overallConfidence };
  } finally {
    if (audioContext.state !== 'closed') {
      await audioContext.close();
    }
  }
}

function formatDetectedAnalysis(analysis?: DetectedVocalAnalysis | null) {
  if (!analysis) {
    return '';
  }

  const parts: string[] = [];

  if (analysis.bpm) {
    const confidence = formatConfidenceValue(analysis.bpmConfidence);
    parts.push(`${analysis.bpm} BPM${confidence ? ` (${confidence})` : ''}`);
  }

  if (analysis.key) {
    const confidence = formatConfidenceValue(analysis.keyConfidence);
    parts.push(`${analysis.key}${confidence ? ` (${confidence})` : ''}`);
  }

  return parts.join(' · ');
}

function getStatusClasses(status?: string) {
  switch (status) {
    case 'completed':
    case 'succeeded':
    case 'generated':
    case 'ready':
      return 'border-emerald-400/40 bg-emerald-500/10 text-emerald-200';
    case 'running':
    case 'recording':
    case 'in_progress':
    case 'ready_for_mix':
    case 'ready_for_master':
      return 'border-sky-400/40 bg-sky-500/10 text-sky-200';
    case 'failed':
      return 'border-rose-400/40 bg-rose-500/10 text-rose-200';
    default:
      return 'border-violet-400/40 bg-violet-500/10 text-violet-200';
  }
}

function prettyStatus(value?: string) {
  return (value || 'queued').replace(/_/g, ' ');
}

function formatRelativeDate(value: string) {
  const date = new Date(value);
  const diffMs = Date.now() - date.getTime();
  const diffHours = Math.max(1, Math.round(diffMs / (1000 * 60 * 60)));

  if (diffHours < 24) {
    return `${diffHours}h ago`;
  }

  const diffDays = Math.round(diffHours / 24);
  return `${diffDays}d ago`;
}

const StudioPage = () => {
  const { currentUser } = useAppSelector((state) => state.auth);
  const canCreateProjects = hasPermission(currentUser, 'CREATE_PROJECTS');

  const [isLoading, setIsLoading] = useState(true);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [errorMessage, setErrorMessage] = useState('');
  const [successMessage, setSuccessMessage] = useState('');
  const [form, setForm] = useState<FormState>(initialForm);
  const [genres, setGenres] = useState<GenreOption[]>([]);
  const [languages, setLanguages] = useState<LanguageOption[]>([]);
  const [masteringPresets, setMasteringPresets] = useState<MasteringPresetOption[]>([]);
  const [aiModels, setAiModels] = useState<AiModelOption[]>([]);
  const [recentSessions, setRecentSessions] = useState<RecentSession[]>([]);
  const [createdSession, setCreatedSession] = useState<CreatedSession | null>(null);
  const [uploadedVocal, setUploadedVocal] = useState<UploadedFile | null>(null);
  const [uploadedVocalFile, setUploadedVocalFile] = useState<File | null>(null);
  const [submittedVocalPreview, setSubmittedVocalPreview] = useState<SubmittedVocalPreview | null>(null);
  const [vocalAnalysis, setVocalAnalysis] = useState<DetectedVocalAnalysis | null>(null);
  const [isUploadingVocal, setIsUploadingVocal] = useState(false);
  const [isAnalyzingVocal, setIsAnalyzingVocal] = useState(false);
  const [isVocalDragActive, setIsVocalDragActive] = useState(false);
  const [vocalUploadError, setVocalUploadError] = useState('');
  const [vocalAnalysisError, setVocalAnalysisError] = useState('');
  const [tapTempoMarks, setTapTempoMarks] = useState<number[]>([]);
  const [tapTempoBpm, setTapTempoBpm] = useState<number | null>(null);
  const [tapTempoStatus, setTapTempoStatus] = useState('Tap 4 to 8 times in rhythm to estimate BPM manually.');

  const vocalFileInputRef = useRef<HTMLInputElement | null>(null);
  const vocalDragDepthRef = useRef(0);
  const lastAutoDetectedValuesRef = useRef({ targetBpm: '', targetKey: '' });

  const selectedGenre = useMemo(
    () => genres.find((genre) => genre.id === form.genreId) || null,
    [form.genreId, genres],
  );

  const selectedPreset = useMemo(
    () => masteringPresets.find((preset) => preset.id === form.masteringPresetId) || null,
    [form.masteringPresetId, masteringPresets],
  );

  const detectedAnalysisLabel = formatDetectedAnalysis(vocalAnalysis);
  const detectedOverallConfidence = formatConfidenceSummary(vocalAnalysis?.overallConfidence);
  const hasDetectedSuggestions = Boolean(vocalAnalysis?.bpm || vocalAnalysis?.key);
  const canApplyDetectedSuggestions = Boolean(
    (vocalAnalysis?.bpm && form.targetBpm !== String(vocalAnalysis.bpm)) || (vocalAnalysis?.key && form.targetKey !== vocalAnalysis.key),
  );
  const lowConfidenceWarning = getLowConfidenceWarning(vocalAnalysis, vocalAnalysisError);
  const showLowConfidenceWarning = Boolean(form.vocalMode === 'upload' && uploadedVocal && lowConfidenceWarning);
  const shouldShowTapTempoAssist = Boolean(
    form.vocalMode === 'upload' && uploadedVocal && (vocalAnalysisError || !vocalAnalysis?.bpm || hasLowConfidence(vocalAnalysis?.bpmConfidence)),
  );
  const tapTempoCount = tapTempoMarks.length;

  const syncDetectedValuesToForm = (analysis: DetectedVocalAnalysis | null, force = false) => {
    if (!analysis) {
      return;
    }

    const detectedValues = {
      targetBpm: analysis.bpm ? String(analysis.bpm) : '',
      targetKey: analysis.key || '',
    };

    setForm((current) => {
      const next = { ...current };

      if (
        detectedValues.targetBpm &&
        (force || !current.targetBpm || current.targetBpm === lastAutoDetectedValuesRef.current.targetBpm)
      ) {
        next.targetBpm = detectedValues.targetBpm;
      }

      if (
        detectedValues.targetKey &&
        (force || !current.targetKey || current.targetKey === lastAutoDetectedValuesRef.current.targetKey)
      ) {
        next.targetKey = detectedValues.targetKey;
      }

      return next;
    });

    if (detectedValues.targetBpm) {
      lastAutoDetectedValuesRef.current.targetBpm = detectedValues.targetBpm;
    }

    if (detectedValues.targetKey) {
      lastAutoDetectedValuesRef.current.targetKey = detectedValues.targetKey;
    }
  };

  const resetVocalPicker = () => {
    if (vocalFileInputRef.current) {
      vocalFileInputRef.current.value = '';
    }

    vocalDragDepthRef.current = 0;
    setIsVocalDragActive(false);
  };

  const resetTapTempo = (message = 'Tap 4 to 8 times in rhythm to estimate BPM manually.') => {
    setTapTempoMarks([]);
    setTapTempoBpm(null);
    setTapTempoStatus(message);
  };

  const loadLaunchpad = async () => {
    const { data } = await axios.get<LaunchpadResponse>('/studio/launchpad');

    setGenres(data.genres || []);
    setLanguages(data.languages || []);
    setMasteringPresets(data.masteringPresets || []);
    setAiModels(data.aiModels || []);
    setRecentSessions(data.recentSessions || []);
    setForm((current) => ({
      ...current,
      genreId: current.genreId || data.genres?.[0]?.id || '',
      languageId: current.languageId || data.languages?.[0]?.id || '',
      masteringPresetId: current.masteringPresetId || data.masteringPresets?.[0]?.id || '',
      targetBpm:
        current.targetBpm ||
        (data.genres?.[0]?.typical_bpm_min ? String(data.genres[0].typical_bpm_min) : ''),
    }));
  };

  useEffect(() => {
    const run = async () => {
      try {
        setIsLoading(true);
        setErrorMessage('');
        await loadLaunchpad();
      } catch (error) {
        console.error('Failed to load studio launchpad:', error);
        setErrorMessage('We could not load the studio launchpad right now. Please refresh and try again.');
      } finally {
        setIsLoading(false);
      }
    };

    run();
  }, []);

  useEffect(() => {
    if (!selectedGenre) {
      return;
    }

    setForm((current) => {
      if (current.targetBpm) {
        return current;
      }

      return {
        ...current,
        targetBpm: selectedGenre.typical_bpm_min ? String(selectedGenre.typical_bpm_min) : '',
      };
    });
  }, [selectedGenre]);

  const handleChange =
    (field: keyof FormState) =>
    (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
      const target = event.target;
      const value = target instanceof HTMLInputElement && target.type === 'checkbox' ? target.checked : target.value;

      setForm((current) => ({
        ...current,
        [field]: value,
      } as FormState));
    };

  const clearUploadedVocal = () => {
    setUploadedVocal(null);
    setUploadedVocalFile(null);
    setVocalAnalysis(null);
    setVocalUploadError('');
    setVocalAnalysisError('');
    setIsAnalyzingVocal(false);
    resetTapTempo();
    resetVocalPicker();
  };

  const handleSelectedVocalFile = async (file: File) => {
    try {
      setIsUploadingVocal(true);
      setIsAnalyzingVocal(false);
      setVocalUploadError('');
      setVocalAnalysisError('');
      setErrorMessage('');
      resetTapTempo();

      FileUploader.validate(file, vocalUploadSchema);
      const remoteFile = (await FileUploader.upload('assets/file_blobs', file, vocalUploadSchema)) as UploadedFile;

      setUploadedVocal(remoteFile);
      setUploadedVocalFile(file);
      setVocalAnalysis(null);

      setIsAnalyzingVocal(true);

      try {
        const analysis = await detectVocalAnalysis(file);
        setVocalAnalysis(analysis);
        syncDetectedValuesToForm(analysis);
      } catch (error) {
        console.error('Failed to analyze uploaded vocal:', error);
        setVocalAnalysis(null);
        setVocalAnalysisError('The vocal uploaded successfully, but automatic BPM/key detection is unavailable for this take.');
      } finally {
        setIsAnalyzingVocal(false);
      }
    } catch (error) {
      console.error('Failed to upload vocal file:', error);
      clearUploadedVocal();
      setVocalUploadError(error instanceof Error ? error.message : 'We could not upload the vocal file. Please try again.');
    } finally {
      setIsUploadingVocal(false);
      resetVocalPicker();
    }
  };

  const handleVocalUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];

    if (!file) {
      return;
    }

    await handleSelectedVocalFile(file);
  };

  const handleVocalDragEnter = (event: DragEvent<HTMLDivElement>) => {
    event.preventDefault();
    event.stopPropagation();

    if (!canCreateProjects || isSubmitting || isUploadingVocal) {
      return;
    }

    vocalDragDepthRef.current += 1;
    setIsVocalDragActive(true);
  };

  const handleVocalDragOver = (event: DragEvent<HTMLDivElement>) => {
    event.preventDefault();
    event.stopPropagation();

    if (!canCreateProjects || isSubmitting || isUploadingVocal) {
      return;
    }

    event.dataTransfer.dropEffect = 'copy';
    setIsVocalDragActive(true);
  };

  const handleVocalDragLeave = (event: DragEvent<HTMLDivElement>) => {
    event.preventDefault();
    event.stopPropagation();

    if (!canCreateProjects || isSubmitting || isUploadingVocal) {
      return;
    }

    vocalDragDepthRef.current = Math.max(0, vocalDragDepthRef.current - 1);

    if (!vocalDragDepthRef.current) {
      setIsVocalDragActive(false);
    }
  };

  const handleVocalDrop = async (event: DragEvent<HTMLDivElement>) => {
    event.preventDefault();
    event.stopPropagation();

    vocalDragDepthRef.current = 0;
    setIsVocalDragActive(false);

    if (!canCreateProjects || isSubmitting || isUploadingVocal) {
      return;
    }

    const file = event.dataTransfer.files?.[0];

    if (!file) {
      return;
    }

    await handleSelectedVocalFile(file);
  };

  const handleTapTempo = () => {
    const now = Date.now();

    setTapTempoMarks((current) => {
      const recentMarks = current.filter((timestamp) => now - timestamp <= 8000);
      const timedOut = Boolean(recentMarks.length && now - recentMarks[recentMarks.length - 1] > 2500);
      const baseMarks = timedOut ? [] : recentMarks;
      const nextMarks = [...baseMarks, now].slice(-8);

      if (timedOut) {
        setTapTempoBpm(null);
        setTapTempoStatus('Tap timing reset after a pause. Start tapping again on the beat.');
      }

      if (nextMarks.length < 4) {
        const tapsRemaining = 4 - nextMarks.length;
        setTapTempoBpm(null);
        setTapTempoStatus(
          `Captured ${nextMarks.length} tap${nextMarks.length === 1 ? '' : 's'}. Tap ${tapsRemaining} more time${tapsRemaining === 1 ? '' : 's'} to estimate BPM.`,
        );
        return nextMarks;
      }

      const intervals = nextMarks
        .slice(1)
        .map((timestamp, index) => timestamp - nextMarks[index])
        .filter((interval) => interval > 0 && interval < 2000);

      if (!intervals.length) {
        setTapTempoBpm(null);
        setTapTempoStatus('Those taps were too uneven to estimate BPM. Try tapping a steady pulse.');
        return nextMarks;
      }

      const averageInterval = intervals.reduce((total, interval) => total + interval, 0) / intervals.length;
      const bpm = normalizeTempo(60000 / averageInterval);
      const bpmValue = String(bpm);

      setTapTempoBpm(bpm);
      setTapTempoStatus(`Tap tempo estimated ${bpm} BPM from ${nextMarks.length} taps. Keep tapping to refine it, or keep this value.`);
      setForm((currentForm) => ({
        ...currentForm,
        targetBpm: bpmValue,
      }));
      lastAutoDetectedValuesRef.current.targetBpm = bpmValue;

      return nextMarks;
    });
  };

  const handleResetTapTempo = () => {
    resetTapTempo();
  };

  const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();

    if (form.vocalMode === 'upload' && !uploadedVocal) {
      setErrorMessage('Upload an MP3 or WAV vocal take before launching the session.');
      return;
    }

    try {
      setIsSubmitting(true);
      setErrorMessage('');
      setSuccessMessage('');

      const { data } = await axios.post<{ message: string; session: CreatedSession }>('/studio/launchpad', {
        ...form,
        vocalUpload: uploadedVocal,
      });

      if (form.vocalMode === 'upload' && uploadedVocal) {
        setSubmittedVocalPreview({
          file: uploadedVocalFile,
          audioUrl: uploadedVocal.publicUrl,
          name: uploadedVocal.name,
          sizeInBytes: uploadedVocal.sizeInBytes,
          analysis: vocalAnalysis,
        });
      } else {
        setSubmittedVocalPreview(null);
      }

      setCreatedSession(data.session);
      setSuccessMessage(data.message);
      setForm((current) => ({
        ...initialForm,
        genreId: current.genreId,
        languageId: current.languageId,
        masteringPresetId: current.masteringPresetId,
        targetBpm: current.targetBpm,
        targetKey: current.targetKey,
      }));
      clearUploadedVocal();
      await loadLaunchpad();
    } catch (error) {
      console.error('Failed to create studio session:', error);
      setErrorMessage(
        axios.isAxiosError(error)
          ? error.response?.data || 'We could not create the session. Please review the form and try again.'
          : 'We could not create the session. Please review the form and try again.',
      );
    } finally {
      setIsSubmitting(false);
    }
  };

  const quickStats = [
    {
      label: 'SA genres ready',
      value: genres.length || '—',
      icon: mdiMusic,
    },
    {
      label: 'Languages supported',
      value: languages.length || '—',
      icon: mdiMicrophone,
    },
    {
      label: 'AI engines online',
      value: aiModels.length || '—',
      icon: mdiRobot,
    },
    {
      label: 'Recent sessions',
      value: recentSessions.length || '0',
      icon: mdiAlbum,
    },
  ];

  return (
    <>
      <Head>
        <title>{getPageTitle('Studio Launchpad')}</title>
      </Head>
      <SectionMain>
        <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Studio Launchpad" main>
          {''}
        </SectionTitleLineWithButton>

        <div className="mb-6 grid gap-6 xl:grid-cols-[1.8fr_1fr]">
          <CardBox className="overflow-hidden border border-violet-500/20 bg-gradient-to-br from-slate-950 via-slate-900 to-violet-950 text-white shadow-2xl shadow-violet-950/30">
            <div className="grid gap-6 lg:grid-cols-[1.5fr_1fr]">
              <div>
                <div className="mb-4 inline-flex items-center rounded-full border border-white/10 bg-white/5 px-3 py-1 text-xs uppercase tracking-[0.24em] text-violet-200">
                  South African AI music workflow
                </div>
                <h1 className="max-w-2xl text-3xl font-semibold leading-tight md:text-4xl">
                  Turn a beat idea into a staged studio session in one launch.
                </h1>
                <p className="mt-4 max-w-2xl text-sm leading-7 text-slate-300 md:text-base">
                  Pick your genre, vocal workflow, language, mastering target, and export format. The launchpad instantly creates a linked project, song, AI generation request, arrangement, mix, mastering, metadata, artwork, and export job.
                </p>
                <div className="mt-6 flex flex-wrap gap-3">
                  <Link
                    href="/projects/projects-list"
                    className="inline-flex items-center rounded-full border border-white/10 bg-white/10 px-4 py-2 text-sm font-medium text-white transition hover:bg-white/15"
                  >
                    View all projects
                    <BaseIcon path={mdiChevronRight} size={16} className="ml-1" />
                  </Link>
                  <Link
                    href="/generation_requests/generation_requests-list"
                    className="inline-flex items-center rounded-full border border-white/10 px-4 py-2 text-sm font-medium text-slate-200 transition hover:border-violet-300/40 hover:text-white"
                  >
                    AI queue
                    <BaseIcon path={mdiChevronRight} size={16} className="ml-1" />
                  </Link>
                </div>
              </div>

              <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-1">
                {quickStats.map((item) => (
                  <div key={item.label} className="rounded-2xl border border-white/10 bg-white/5 p-4 backdrop-blur">
                    <div className="flex items-center justify-between">
                      <span className="text-xs uppercase tracking-[0.18em] text-slate-400">{item.label}</span>
                      <BaseIcon path={item.icon} size={22} className="text-violet-200" />
                    </div>
                    <div className="mt-3 text-3xl font-semibold text-white">{item.value}</div>
                  </div>
                ))}
              </div>
            </div>
          </CardBox>

          <CardBox className="border border-slate-800 bg-slate-950 text-white">
            <div className="mb-5 flex items-center justify-between">
              <div>
                <p className="text-xs uppercase tracking-[0.24em] text-violet-300">Active AI chain</p>
                <h2 className="mt-2 text-xl font-semibold">What gets staged automatically</h2>
              </div>
              <BaseIcon path={mdiWaveform} size={26} className="text-violet-300" />
            </div>
            <div className="space-y-4">
              {stageCards.map((card) => (
                <div key={card.label} className="rounded-2xl border border-white/10 bg-white/5 p-4">
                  <div className="flex items-start gap-3">
                    <div className="rounded-xl border border-white/10 bg-white/10 p-2 text-violet-200">
                      <BaseIcon path={card.icon} size={20} />
                    </div>
                    <div>
                      <div className="font-medium text-white">{card.label}</div>
                      <p className="mt-1 text-sm leading-6 text-slate-300">{card.detail}</p>
                    </div>
                  </div>
                </div>
              ))}
            </div>
          </CardBox>
        </div>

        {errorMessage ? (
          <NotificationBar color="danger" icon={mdiClockOutline}>
            {errorMessage}
          </NotificationBar>
        ) : null}

        {successMessage ? (
          <NotificationBar color="success" icon={mdiCheckCircleOutline}>
            {successMessage}
          </NotificationBar>
        ) : null}

        {!canCreateProjects ? (
          <NotificationBar color="warning" icon={mdiClockOutline}>
            Your role can review studio sessions, but it cannot launch new ones yet. Ask an admin for project creation access.
          </NotificationBar>
        ) : null}

        <div className="grid gap-6 2xl:grid-cols-[1.55fr_1fr]">
          <CardBox className="border border-slate-800 bg-slate-950 text-white">
            <div className="mb-6 flex items-center justify-between gap-4">
              <div>
                <p className="text-xs uppercase tracking-[0.24em] text-violet-300">First delivery workflow</p>
                <h2 className="mt-2 text-2xl font-semibold">Create a launch-ready studio session</h2>
              </div>
              <div className="rounded-full border border-violet-500/30 bg-violet-500/10 px-4 py-2 text-xs uppercase tracking-[0.2em] text-violet-200">
                Project → Song → Mix → Master → Export
              </div>
            </div>

            <form onSubmit={handleSubmit}>

              {form.vocalMode === 'upload' ? (
                <FormField label="Vocal upload" help="Attach the raw MP3 or WAV take so beat matching and vocal asset linking can happen immediately.">
                  <div className="rounded-3xl border border-white/10 bg-white/5 p-5">
                    <input
                      ref={vocalFileInputRef}
                      type="file"
                      className="hidden"
                      accept=".mp3,.wav,audio/mpeg,audio/wav,audio/x-wav"
                      onChange={handleVocalUpload}
                      disabled={!canCreateProjects || isSubmitting || isUploadingVocal}
                    />

                    <div
                      role="button"
                      tabIndex={canCreateProjects ? 0 : -1}
                      onClick={() => {
                        if (!canCreateProjects || isSubmitting || isUploadingVocal) {
                          return;
                        }

                        vocalFileInputRef.current?.click();
                      }}
                      onKeyDown={(event) => {
                        if (event.key === 'Enter' || event.key === ' ') {
                          event.preventDefault();

                          if (!canCreateProjects || isSubmitting || isUploadingVocal) {
                            return;
                          }

                          vocalFileInputRef.current?.click();
                        }
                      }}
                      onDragEnter={handleVocalDragEnter}
                      onDragOver={handleVocalDragOver}
                      onDragLeave={handleVocalDragLeave}
                      onDrop={handleVocalDrop}
                      className={`rounded-3xl border border-dashed p-5 transition ${
                        !canCreateProjects || isSubmitting
                          ? 'cursor-not-allowed border-white/10 bg-slate-950/40 text-slate-500'
                          : isVocalDragActive
                            ? 'cursor-pointer border-emerald-300/60 bg-emerald-500/10 shadow-lg shadow-emerald-900/20'
                            : 'cursor-pointer border-violet-300/20 bg-slate-950/50 hover:border-violet-300/40 hover:bg-slate-900/80'
                      }`}
                    >
                      <div className="flex flex-wrap items-center justify-between gap-3">
                        <div>
                          <div className="text-xs uppercase tracking-[0.18em] text-slate-400">Drag & drop vocal intake</div>
                          <div className="mt-2 text-base font-medium text-white">
                            {isUploadingVocal ? 'Uploading vocal…' : uploadedVocal ? 'Replace the current vocal take' : 'Drop an MP3/WAV here or click to browse'}
                          </div>
                          <p className="mt-2 max-w-2xl text-sm leading-6 text-slate-300">
                            Upload starts immediately, then the browser suggests BPM and key from the take so you can match the beat faster.
                          </p>
                        </div>

                        <div className="rounded-full border border-white/10 px-3 py-1 text-xs uppercase tracking-[0.16em] text-slate-300">
                          {isVocalDragActive ? 'Release to upload' : uploadedVocal ? 'Take attached' : 'Awaiting file'}
                        </div>
                      </div>

                      <div className="mt-4 flex flex-wrap items-center gap-3">
                        <span
                          className={`inline-flex items-center rounded-full border px-4 py-2 text-sm font-medium transition ${
                            !canCreateProjects || isSubmitting || isUploadingVocal
                              ? 'border-white/10 bg-slate-900/40 text-slate-500'
                              : 'border-violet-400/30 bg-violet-500/10 text-violet-100 hover:bg-violet-500/20'
                          }`}
                        >
                          {isUploadingVocal ? 'Uploading vocal…' : uploadedVocal ? 'Choose another file' : 'Browse files'}
                        </span>

                        {uploadedVocal ? (
                          <button
                            type="button"
                            onClick={(event) => {
                              event.stopPropagation();
                              clearUploadedVocal();
                            }}
                            className="inline-flex items-center rounded-full border border-white/10 px-4 py-2 text-sm font-medium text-slate-300 transition hover:border-rose-300/30 hover:text-white"
                          >
                            Remove upload
                          </button>
                        ) : null}

                        <div className="text-xs uppercase tracking-[0.18em] text-slate-400">
                          {uploadedVocal ? 'Waveform ready · asset will attach on launch' : 'No vocal take attached yet'}
                        </div>
                      </div>
                    </div>

                    {vocalUploadError ? <p className="mt-4 text-sm text-rose-300">{vocalUploadError}</p> : null}
                    {vocalAnalysisError ? <p className="mt-4 text-sm text-amber-200">{vocalAnalysisError}</p> : null}

                    <div className="mt-4">
                      <AudioWaveformPreview
                        file={uploadedVocalFile}
                        audioUrl={uploadedVocal?.publicUrl}
                        isLoading={isUploadingVocal || isAnalyzingVocal}
                        title="Uploaded vocal take"
                        subtitle={uploadedVocal ? `${uploadedVocal.name}${formatFileSize(uploadedVocal.sizeInBytes) ? ` · ${formatFileSize(uploadedVocal.sizeInBytes)}` : ''}` : undefined}
                        emptyMessage="Upload a raw vocal take to preview the waveform and confirm the file that will be linked into the generated session."
                      />
                    </div>
                  </div>
                </FormField>
              ) : null}
              <div className="grid gap-6 md:grid-cols-2">
                <FormField label="Project title" help="Use a release-ready working title for the session.">
                  <input
                    name="title"
                    placeholder="Midnight Log Drum Prayer"
                    value={form.title}
                    onChange={handleChange('title')}
                    disabled={!canCreateProjects || isSubmitting}
                  />
                </FormField>

                <FormField label="Main vocal language" help="Used to stage vocal processing and metadata context.">
                  <select value={form.languageId} onChange={handleChange('languageId')} disabled={!canCreateProjects || isSubmitting}>
                    <option value="">Select language</option>
                    {languages.map((language) => (
                      <option key={language.id} value={language.id}>
                        {language.name}
                        {language.iso_code ? ` (${language.iso_code})` : ''}
                      </option>
                    ))}
                  </select>
                </FormField>
              </div>

              <div className="grid gap-6 md:grid-cols-3">
                <FormField label="South African genre" help="Choose the dominant production style for the generated beat.">
                  <select value={form.genreId} onChange={handleChange('genreId')} disabled={!canCreateProjects || isSubmitting}>
                    <option value="">Select genre</option>
                    {genres.map((genre) => (
                      <option key={genre.id} value={genre.id}>
                        {genre.name}
                      </option>
                    ))}
                  </select>
                </FormField>

                <FormField label="Mood" help="Controls arrangement, energy, and mastering direction.">
                  <select value={form.mood} onChange={handleChange('mood')} disabled={!canCreateProjects || isSubmitting}>
                    {moodOptions.map((mood) => (
                      <option key={mood} value={mood}>
                        {prettyStatus(mood)}
                      </option>
                    ))}
                  </select>
                </FormField>

                <FormField label="Vocal workflow" help="Choose whether this starts from vocals, a planned recording, or an instrumental draft.">
                  <select value={form.vocalMode} onChange={handleChange('vocalMode')} disabled={!canCreateProjects || isSubmitting}>
                    {vocalModes.map((mode) => (
                      <option key={mode.value} value={mode.value}>
                        {mode.title}
                      </option>
                    ))}
                  </select>
                </FormField>
              </div>

              <FormField label="Beat prompt" help="Describe the groove, emotion, instrumentation, and arrangement vibe.">
                <textarea
                  name="promptText"
                  placeholder="Soulful Amapiano with warm log drum movement, emotional piano chords, and a radio-ready vocal pocket for Xitsonga hooks."
                  value={form.promptText}
                  onChange={handleChange('promptText')}
                  disabled={!canCreateProjects || isSubmitting}
                />
              </FormField>

              <div className="grid gap-6 md:grid-cols-2">
                <FormField label="Creative notes" help="Optional notes for mix balance, vocal texture, or arrangement details.">
                  <textarea
                    name="notes"
                    placeholder="Keep the intro DJ-friendly, push the bass in the chorus, and leave space for call-and-response adlibs."
                    value={form.notes}
                    onChange={handleChange('notes')}
                    disabled={!canCreateProjects || isSubmitting}
                  />
                </FormField>

                <div className="rounded-3xl border border-white/10 bg-white/5 p-5">
                  <div className="grid gap-5 md:grid-cols-2">
                    <FormField label="Target BPM" help="You can refine the genre default.">
                      <input
                        name="targetBpm"
                        type="number"
                        min={60}
                        max={180}
                        value={form.targetBpm}
                        onChange={handleChange('targetBpm')}
                        disabled={!canCreateProjects || isSubmitting}
                      />
                    </FormField>

                    <FormField label="Target key" help="Optional if you already know the vocal key center.">
                      <input
                        name="targetKey"
                        placeholder="F# minor"
                        value={form.targetKey}
                        onChange={handleChange('targetKey')}
                        disabled={!canCreateProjects || isSubmitting}
                      />
                    </FormField>
                  </div>

                  {shouldShowTapTempoAssist ? (
                    <div className="mb-5 rounded-2xl border border-amber-300/25 bg-amber-500/10 p-4">
                      <div className="flex flex-wrap items-start justify-between gap-3">
                        <div>
                          <div className="text-xs uppercase tracking-[0.18em] text-amber-100">Manual BPM assist</div>
                          <p className="mt-2 text-sm leading-6 text-amber-50">
                            Automatic BPM confidence is low for this take, so you can tap the pulse manually to lock in a steadier tempo.
                          </p>
                        </div>

                        <div className="flex flex-wrap gap-2">
                          <button
                            type="button"
                            onClick={handleTapTempo}
                            disabled={!canCreateProjects || isSubmitting || isUploadingVocal}
                            className="inline-flex items-center rounded-full border border-amber-200/40 bg-white/10 px-4 py-2 text-sm font-medium text-amber-50 transition hover:bg-white/15 disabled:cursor-not-allowed disabled:opacity-60"
                          >
                            Tap tempo
                          </button>
                          <button
                            type="button"
                            onClick={handleResetTapTempo}
                            disabled={!tapTempoCount}
                            className="inline-flex items-center rounded-full border border-white/10 px-4 py-2 text-sm font-medium text-slate-200 transition hover:border-white/20 hover:text-white disabled:cursor-not-allowed disabled:opacity-50"
                          >
                            Reset taps
                          </button>
                        </div>
                      </div>

                      <div className="mt-3 flex flex-wrap gap-2 text-xs uppercase tracking-[0.16em] text-amber-50">
                        <span className="rounded-full border border-amber-200/30 bg-white/10 px-3 py-1">{tapTempoCount || 0} taps captured</span>
                        {tapTempoBpm ? (
                          <span className="rounded-full border border-emerald-300/30 bg-emerald-500/10 px-3 py-1 text-emerald-100">Tap BPM {tapTempoBpm}</span>
                        ) : null}
                      </div>

                      <p className="mt-3 text-sm leading-6 text-amber-50/90">{tapTempoStatus}</p>
                    </div>
                  ) : null}

                  {form.vocalMode === 'upload' ? (
                    <div className="mb-5 rounded-2xl border border-white/10 bg-slate-950/60 p-4">
                      <div className="flex flex-wrap items-start justify-between gap-3">
                        <div>
                          <div className="flex flex-wrap items-center gap-2 text-xs uppercase tracking-[0.18em] text-slate-400">
                            <span>Auto-detected from vocal</span>
                            <span
                              className="inline-flex items-center rounded-full border border-white/10 bg-white/5 px-2 py-1 text-[10px] tracking-[0.16em] text-slate-300"
                              title="High = stable signal and strong detector match. Medium = usable estimate, but verify by ear. Low = noisy or ambiguous take, so check manually."
                            >
                              <BaseIcon path={mdiInformationOutline} size={12} className="mr-1 text-sky-200" />
                              Confidence guide
                            </span>
                          </div>
                          <p className="mt-2 text-sm leading-6 text-slate-300">
                            {isAnalyzingVocal
                              ? 'Analyzing the uploaded take for BPM and key suggestions…'
                              : detectedAnalysisLabel
                                ? `Suggested values: ${detectedAnalysisLabel}${detectedOverallConfidence ? ` · ${detectedOverallConfidence}` : ''}`
                                : 'Upload a vocal take to auto-fill BPM and key suggestions here.'}
                          </p>
                        </div>

                        {hasDetectedSuggestions && canApplyDetectedSuggestions ? (
                          <button
                            type="button"
                            onClick={() => syncDetectedValuesToForm(vocalAnalysis, true)}
                            className="inline-flex items-center rounded-full border border-emerald-300/30 bg-emerald-500/10 px-4 py-2 text-sm font-medium text-emerald-100 transition hover:bg-emerald-500/20"
                          >
                            Apply suggestions
                          </button>
                        ) : null}
                      </div>

                      {hasDetectedSuggestions ? (
                        <div className="mt-3 flex flex-wrap gap-2 text-xs uppercase tracking-[0.16em] text-slate-200">
                          {vocalAnalysis?.bpm ? (
                            <span
                              className={`rounded-full border px-3 py-1 ${getConfidenceClasses(vocalAnalysis.bpmConfidence)}`}
                              title={getConfidenceTooltip('BPM detection', vocalAnalysis.bpmConfidence)}
                            >
                              BPM {vocalAnalysis.bpm} · {formatConfidenceSummary(vocalAnalysis.bpmConfidence) || getConfidenceLabel(vocalAnalysis.bpmConfidence)}
                            </span>
                          ) : null}
                          {vocalAnalysis?.key ? (
                            <span
                              className={`rounded-full border px-3 py-1 ${getConfidenceClasses(vocalAnalysis.keyConfidence)}`}
                              title={getConfidenceTooltip('Key detection', vocalAnalysis.keyConfidence)}
                            >
                              Key {vocalAnalysis.key} · {formatConfidenceSummary(vocalAnalysis.keyConfidence) || getConfidenceLabel(vocalAnalysis.keyConfidence)}
                            </span>
                          ) : null}
                          {detectedOverallConfidence ? (
                            <span
                              className={`rounded-full border px-3 py-1 ${getConfidenceClasses(vocalAnalysis?.overallConfidence)}`}
                              title={getConfidenceTooltip('Overall vocal analysis', vocalAnalysis?.overallConfidence)}
                            >
                              Overall {detectedOverallConfidence}
                            </span>
                          ) : null}
                        </div>
                      ) : null}

                      {showLowConfidenceWarning ? (
                        <div className="mt-4 rounded-2xl border border-rose-300/25 bg-rose-500/10 p-4 text-sm leading-6 text-rose-50">
                          <div className="flex items-start gap-3">
                            <BaseIcon path={mdiAlertCircleOutline} size={18} className="mt-1 text-rose-200" />
                            <div>
                              <div className="text-xs uppercase tracking-[0.16em] text-rose-100">Low-confidence vocal warning</div>
                              <p className="mt-2">{lowConfidenceWarning}</p>
                            </div>
                          </div>
                        </div>
                      ) : null}
                    </div>
                  ) : null}

                  <div className="grid gap-5 md:grid-cols-2">
                    <FormField label="Mastering preset" help="This stages the master destination and loudness profile.">
                      <select
                        value={form.masteringPresetId}
                        onChange={handleChange('masteringPresetId')}
                        disabled={!canCreateProjects || isSubmitting}
                      >
                        <option value="">Select mastering preset</option>
                        {masteringPresets.map((preset) => (
                          <option key={preset.id} value={preset.id}>
                            {preset.name}
                          </option>
                        ))}
                      </select>
                    </FormField>

                    <FormField label="Export target" help="Choose the initial delivery format to queue.">
                      <select value={form.exportFormat} onChange={handleChange('exportFormat')} disabled={!canCreateProjects || isSubmitting}>
                        <option value="wav">WAV · studio quality</option>
                        <option value="mp3">MP3 · quick share</option>
                        <option value="stems_zip">Stems ZIP · distribution prep</option>
                      </select>
                    </FormField>
                  </div>

                  <label className="mt-2 flex items-center gap-3 rounded-2xl border border-white/10 bg-slate-900/60 px-4 py-3 text-sm text-slate-200">
                    <input
                      type="checkbox"
                      checked={form.includeStems}
                      onChange={handleChange('includeStems')}
                      disabled={!canCreateProjects || isSubmitting}
                      className="h-4 w-4 rounded border-slate-600 bg-slate-950 text-violet-400 focus:ring-violet-500"
                    />
                    Include stems export in the first session package.
                  </label>
                </div>
              </div>

              <div className="mt-6 flex flex-wrap gap-3">
                <BaseButton
                  type="submit"
                  color="info"
                  label={isSubmitting ? 'Launching session…' : 'Launch studio session'}
                  icon={mdiRobot}
                  disabled={!canCreateProjects || isSubmitting || isLoading}
                  className="!rounded-full !px-6"
                />
                <BaseButton
                  color="white"
                  outline
                  label="Open songs"
                  href="/songs/songs-list"
                  icon={mdiAlbum}
                  className="!rounded-full !px-6 !text-slate-200"
                />
              </div>
            </form>
          </CardBox>

          <div className="space-y-6">
            <CardBox className="border border-slate-800 bg-slate-950 text-white">
              <div className="flex items-start justify-between gap-4">
                <div>
                  <p className="text-xs uppercase tracking-[0.24em] text-violet-300">Session preview</p>
                  <h3 className="mt-2 text-xl font-semibold">Current setup</h3>
                </div>
                <BaseIcon path={mdiExportVariant} size={24} className="text-violet-300" />
              </div>

              <div className="mt-5 space-y-4 text-sm text-slate-300">
                <div className="rounded-2xl border border-white/10 bg-white/5 p-4">
                  <div className="text-xs uppercase tracking-[0.2em] text-slate-400">Genre DNA</div>
                  <div className="mt-2 text-lg font-medium text-white">{selectedGenre?.name || 'Choose a genre'}</div>
                  <p className="mt-2 leading-6 text-slate-300">{selectedGenre?.description || 'South African groove details will appear here once you pick a genre.'}</p>
                  {selectedGenre?.typical_bpm_min || selectedGenre?.typical_bpm_max ? (
                    <div className="mt-3 text-xs uppercase tracking-[0.18em] text-violet-200">
                      Typical BPM {selectedGenre?.typical_bpm_min || '—'}–{selectedGenre?.typical_bpm_max || '—'}
                    </div>
                  ) : null}
                </div>

                <div className="rounded-2xl border border-white/10 bg-white/5 p-4">
                  <div className="text-xs uppercase tracking-[0.2em] text-slate-400">Mastering target</div>
                  <div className="mt-2 text-lg font-medium text-white">{selectedPreset?.name || 'Select a preset'}</div>
                  <p className="mt-2 leading-6 text-slate-300">
                    {selectedPreset
                      ? `${prettyStatus(selectedPreset.target)} master${selectedPreset.lufs_target ? ` · LUFS ${selectedPreset.lufs_target}` : ''}${selectedPreset.true_peak_db ? ` · Peak ${selectedPreset.true_peak_db} dB` : ''}`
                      : 'Choose how the first export should be prepared for streaming, radio, or club playback.'}
                  </p>
                </div>

                <div className="rounded-2xl border border-white/10 bg-white/5 p-4">
                  <div className="text-xs uppercase tracking-[0.2em] text-slate-400">Vocal route</div>
                  <div className="mt-2 text-lg font-medium text-white">
                    {vocalModes.find((mode) => mode.value === form.vocalMode)?.title || 'Upload vocal'}
                  </div>
                  <p className="mt-2 leading-6 text-slate-300">
                    {vocalModes.find((mode) => mode.value === form.vocalMode)?.description}
                  </p>

                  {form.vocalMode === 'upload' ? (
                    <div className="mt-4 rounded-2xl border border-white/10 bg-slate-950/60 p-4">
                      <div className="text-xs uppercase tracking-[0.16em] text-slate-500">Uploaded take</div>
                      {uploadedVocal ? (
                        <>
                          <div className="mt-2 text-sm font-medium text-white">
                            {uploadedVocal.name}
                            {formatFileSize(uploadedVocal.sizeInBytes) ? ` · ${formatFileSize(uploadedVocal.sizeInBytes)}` : ''}
                          </div>
                          <div className="mt-1 text-xs uppercase tracking-[0.16em] text-emerald-300">Ready for beat matching + asset attachment</div>
                          {isAnalyzingVocal ? (
                            <div className="mt-2 text-xs uppercase tracking-[0.16em] text-sky-200">Analyzing BPM/key from the vocal…</div>
                          ) : detectedAnalysisLabel ? (
                            <div className="mt-2 text-xs uppercase tracking-[0.16em] text-violet-200">
                              Suggested {detectedAnalysisLabel}
                              {detectedOverallConfidence ? ` · ${detectedOverallConfidence}` : ''}
                            </div>
                          ) : null}

                          {showLowConfidenceWarning ? (
                            <div className="mt-3 rounded-2xl border border-rose-300/20 bg-rose-500/10 px-3 py-2 text-xs leading-5 text-rose-100">
                              {lowConfidenceWarning}
                            </div>
                          ) : null}
                        </>
                      ) : (
                        <p className="mt-2 text-sm leading-6 text-slate-400">
                          Add an MP3 or WAV vocal take to make the “upload vocal and match beat” workflow fully functional.
                        </p>
                      )}
                    </div>
                  ) : null}
                </div>
              </div>
            </CardBox>

            <CardBox className="border border-slate-800 bg-slate-950 text-white">
              <div className="flex items-center justify-between gap-3">
                <div>
                  <p className="text-xs uppercase tracking-[0.24em] text-violet-300">AI engines</p>
                  <h3 className="mt-2 text-xl font-semibold">Available models</h3>
                </div>
                <BaseIcon path={mdiRobot} size={24} className="text-violet-300" />
              </div>
              <div className="mt-5 space-y-3">
                {aiModels.length ? (
                  aiModels.map((model) => (
                    <div key={model.id} className="rounded-2xl border border-white/10 bg-white/5 p-4">
                      <div className="flex items-center justify-between gap-3">
                        <div>
                          <div className="font-medium text-white">{model.name}</div>
                          <p className="text-sm text-slate-300">
                            {prettyStatus(model.model_type)} · {model.provider || 'Internal'}
                            {model.version ? ` · ${model.version}` : ''}
                          </p>
                        </div>
                        <BaseIcon path={mdiCheckCircleOutline} size={20} className="text-emerald-300" />
                      </div>
                    </div>
                  ))
                ) : (
                  <div className="rounded-2xl border border-dashed border-white/10 bg-white/5 p-4 text-sm text-slate-300">
                    No active AI models are visible for this workspace yet.
                  </div>
                )}
              </div>
            </CardBox>
          </div>
        </div>

        {createdSession ? (
          <CardBox className="mt-6 border border-emerald-500/20 bg-gradient-to-br from-emerald-950/70 via-slate-950 to-slate-950 text-white">
            <div className="mb-6 flex flex-wrap items-center justify-between gap-4">
              <div>
                <p className="text-xs uppercase tracking-[0.24em] text-emerald-300">Session created</p>
                <h2 className="mt-2 text-2xl font-semibold">Everything is linked and ready for review</h2>
              </div>
              <span className="rounded-full border border-emerald-400/30 bg-emerald-500/10 px-4 py-2 text-xs uppercase tracking-[0.2em] text-emerald-200">
                End-to-end MVP slice complete
              </span>
            </div>

            <div className="grid gap-4 lg:grid-cols-3">
              {[
                { label: 'Project', item: createdSession.project, icon: mdiMusic },
                { label: 'Song', item: createdSession.song, icon: mdiAlbum },
                { label: 'Generation', item: createdSession.generationRequest, icon: mdiRobot },
                { label: 'Recording', item: createdSession.recordingSession, icon: mdiMicrophone },
                { label: 'Vocal asset', item: createdSession.vocalAsset, icon: mdiMicrophone },
                { label: 'Mix', item: createdSession.mixSession, icon: mdiWaveform },
                { label: 'Master', item: createdSession.masteringSession, icon: mdiTuneVariant },
                { label: 'Export', item: createdSession.exportJob, icon: mdiExportVariant },
                { label: 'Metadata', item: createdSession.songMetadata, icon: mdiCheckCircleOutline },
                { label: 'Artwork', item: createdSession.coverArtwork, icon: mdiOpenInNew },
              ].map((entry) =>
                entry.item ? (
                  <Link
                    key={entry.label}
                    href={entry.item.href}
                    className="rounded-2xl border border-white/10 bg-white/5 p-4 transition hover:border-emerald-300/40 hover:bg-white/10"
                  >
                    <div className="flex items-center justify-between gap-3">
                      <div className="flex items-center gap-3">
                        <div className="rounded-xl border border-white/10 bg-white/10 p-2 text-emerald-200">
                          <BaseIcon path={entry.icon} size={18} />
                        </div>
                        <div>
                          <div className="text-xs uppercase tracking-[0.18em] text-slate-400">{entry.label}</div>
                          <div className="mt-1 text-base font-medium text-white">
                            {entry.item.title || entry.item.name || prettyStatus(entry.item.format || entry.item.status)}
                          </div>
                        </div>
                      </div>
                      <BaseIcon path={mdiChevronRight} size={18} className="text-slate-400" />
                    </div>
                  </Link>
                ) : null,
              )}
            </div>

            <div className={`mt-6 grid gap-6 ${submittedVocalPreview ? 'lg:grid-cols-3' : 'lg:grid-cols-2'}`}>
              {submittedVocalPreview ? (
                <div className="rounded-2xl border border-white/10 bg-white/5 p-5">
                  <div className="flex flex-wrap items-start justify-between gap-3">
                    <div>
                      <div className="text-xs uppercase tracking-[0.2em] text-slate-400">Submitted vocal preview</div>
                      <div className="mt-2 text-base font-medium text-white">
                        {submittedVocalPreview.name}
                        {formatFileSize(submittedVocalPreview.sizeInBytes) ? ` · ${formatFileSize(submittedVocalPreview.sizeInBytes)}` : ''}
                      </div>
                      <p className="mt-2 text-sm leading-6 text-slate-300">This is the exact vocal take attached to the session you just launched.</p>
                    </div>

                    {createdSession.vocalAsset ? (
                      <Link
                        href={createdSession.vocalAsset.href}
                        className="inline-flex items-center rounded-full border border-white/10 px-4 py-2 text-sm font-medium text-emerald-100 transition hover:border-emerald-300/40 hover:text-white"
                      >
                        Open asset
                        <BaseIcon path={mdiChevronRight} size={16} className="ml-1" />
                      </Link>
                    ) : null}
                  </div>

                  <div className="mt-4">
                    <AudioWaveformPreview
                      file={submittedVocalPreview.file}
                      audioUrl={submittedVocalPreview.audioUrl}
                      title="Launched vocal waveform"
                      subtitle={submittedVocalPreview.name}
                      emptyMessage="The uploaded take used for this session will appear here when available."
                    />
                  </div>

                  {submittedVocalPreview.analysis ? (
                    <div className="mt-4 flex flex-wrap gap-2 text-xs uppercase tracking-[0.16em] text-slate-200">
                      {submittedVocalPreview.analysis.bpm ? (
                        <span
                          className={`rounded-full border px-3 py-1 ${getConfidenceClasses(submittedVocalPreview.analysis.bpmConfidence)}`}
                          title={getConfidenceTooltip('Submitted BPM detection', submittedVocalPreview.analysis.bpmConfidence)}
                        >
                          BPM {submittedVocalPreview.analysis.bpm} ·{' '}
                          {formatConfidenceSummary(submittedVocalPreview.analysis.bpmConfidence) || getConfidenceLabel(submittedVocalPreview.analysis.bpmConfidence)}
                        </span>
                      ) : null}
                      {submittedVocalPreview.analysis.key ? (
                        <span
                          className={`rounded-full border px-3 py-1 ${getConfidenceClasses(submittedVocalPreview.analysis.keyConfidence)}`}
                          title={getConfidenceTooltip('Submitted key detection', submittedVocalPreview.analysis.keyConfidence)}
                        >
                          Key {submittedVocalPreview.analysis.key} ·{' '}
                          {formatConfidenceSummary(submittedVocalPreview.analysis.keyConfidence) || getConfidenceLabel(submittedVocalPreview.analysis.keyConfidence)}
                        </span>
                      ) : null}
                      {formatConfidenceSummary(submittedVocalPreview.analysis.overallConfidence) ? (
                        <span
                          className={`rounded-full border px-3 py-1 ${getConfidenceClasses(submittedVocalPreview.analysis.overallConfidence)}`}
                          title={getConfidenceTooltip('Submitted overall vocal analysis', submittedVocalPreview.analysis.overallConfidence)}
                        >
                          Overall {formatConfidenceSummary(submittedVocalPreview.analysis.overallConfidence)}
                        </span>
                      ) : null}
                    </div>
                  ) : null}

                  {getLowConfidenceWarning(submittedVocalPreview.analysis) ? (
                    <div className="mt-4 rounded-2xl border border-rose-300/20 bg-rose-500/10 px-4 py-3 text-sm leading-6 text-rose-50">
                      <div className="flex items-start gap-3">
                        <BaseIcon path={mdiAlertCircleOutline} size={18} className="mt-1 text-rose-200" />
                        <div>
                          <div className="text-xs uppercase tracking-[0.16em] text-rose-100">Review this take before publishing</div>
                          <p className="mt-2">{getLowConfidenceWarning(submittedVocalPreview.analysis)}</p>
                        </div>
                      </div>
                    </div>
                  ) : null}
                </div>
              ) : null}

              <div className="rounded-2xl border border-white/10 bg-white/5 p-5">
                <div className="text-xs uppercase tracking-[0.2em] text-slate-400">Arrangement builder</div>
                <div className="mt-4 space-y-3">
                  {createdSession.arrangementSections.map((section) => (
                    <div key={section.id} className="flex items-center justify-between gap-4 rounded-2xl border border-white/10 bg-slate-950/60 px-4 py-3">
                      <div>
                        <div className="font-medium text-white">{section.label}</div>
                        <div className="text-sm text-slate-400">{prettyStatus(section.section_type)}</div>
                      </div>
                      <div className="text-right text-sm text-slate-300">
                        <div>Bar {section.start_bar}</div>
                        <div>{section.bar_length} bars</div>
                      </div>
                    </div>
                  ))}
                </div>
              </div>

              <div className="rounded-2xl border border-white/10 bg-white/5 p-5">
                <div className="text-xs uppercase tracking-[0.2em] text-slate-400">Track blueprint</div>
                <div className="mt-4 space-y-3">
                  {createdSession.tracks.map((track) => (
                    <div key={track.id} className="flex items-center justify-between gap-4 rounded-2xl border border-white/10 bg-slate-950/60 px-4 py-3">
                      <div>
                        <div className="font-medium text-white">{track.name}</div>
                        <div className="text-sm text-slate-400">{prettyStatus(track.track_type)}</div>
                      </div>
                      <div className="rounded-full border border-violet-400/30 bg-violet-500/10 px-3 py-1 text-xs uppercase tracking-[0.16em] text-violet-200">
                        {prettyStatus(track.instrument)}
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            </div>
          </CardBox>
        ) : null}

        <CardBox className="mt-6 border border-slate-800 bg-slate-950 text-white">
          <div className="mb-6 flex flex-wrap items-center justify-between gap-4">
            <div>
              <p className="text-xs uppercase tracking-[0.24em] text-violet-300">Recent work</p>
              <h2 className="mt-2 text-2xl font-semibold">Recent studio sessions</h2>
            </div>
            <Link
              href="/projects/projects-list"
              className="inline-flex items-center rounded-full border border-white/10 px-4 py-2 text-sm font-medium text-slate-200 transition hover:border-violet-300/40 hover:text-white"
            >
              Full project library
              <BaseIcon path={mdiOpenInNew} size={16} className="ml-2" />
            </Link>
          </div>

          {isLoading ? (
            <div className="rounded-2xl border border-white/10 bg-white/5 p-6 text-sm text-slate-300">
              Loading the latest studio sessions…
            </div>
          ) : recentSessions.length ? (
            <div className="grid gap-4 xl:grid-cols-2">
              {recentSessions.map((session) => (
                <div key={session.id} className="rounded-3xl border border-white/10 bg-white/5 p-5">
                  <div className="flex flex-wrap items-start justify-between gap-3">
                    <div>
                      <div className="text-xs uppercase tracking-[0.18em] text-slate-400">
                        {session.genre?.name || 'Studio session'}
                      </div>
                      <h3 className="mt-2 text-xl font-semibold text-white">{session.name}</h3>
                    </div>
                    <div className={`rounded-full border px-3 py-1 text-xs uppercase tracking-[0.16em] ${getStatusClasses(session.status)}`}>
                      {prettyStatus(session.status)}
                    </div>
                  </div>

                  <div className="mt-4 flex flex-wrap gap-2 text-xs uppercase tracking-[0.16em] text-slate-300">
                    {session.target_bpm ? <span className="rounded-full border border-white/10 px-3 py-1">{session.target_bpm} BPM</span> : null}
                    {session.target_key ? <span className="rounded-full border border-white/10 px-3 py-1">{session.target_key}</span> : null}
                    {session.mood ? <span className="rounded-full border border-white/10 px-3 py-1">{prettyStatus(session.mood)}</span> : null}
                    <span className="rounded-full border border-white/10 px-3 py-1">Updated {formatRelativeDate(session.updatedAt)}</span>
                  </div>

                  <div className="mt-5 grid gap-3 sm:grid-cols-2">
                    {[
                      session.song ? { label: 'Song', href: session.song.href, status: session.song.title } : null,
                      session.generationRequest
                        ? {
                            label: 'Generation',
                            href: session.generationRequest.href,
                            status: prettyStatus(session.generationRequest.status),
                          }
                        : null,
                      session.mixSession
                        ? { label: 'Mix', href: session.mixSession.href, status: prettyStatus(session.mixSession.status) }
                        : null,
                      session.masteringSession
                        ? {
                            label: 'Master',
                            href: session.masteringSession.href,
                            status: prettyStatus(session.masteringSession.status),
                          }
                        : null,
                      session.exportJob
                        ? {
                            label: 'Export',
                            href: session.exportJob.href,
                            status: `${prettyStatus(session.exportJob.status)} · ${session.exportJob.format.toUpperCase()}`,
                          }
                        : null,
                    ]
                      .filter(Boolean)
                      .map((item) => (
                        <Link
                          key={`${session.id}-${item?.label}`}
                          href={item?.href || session.projectHref}
                          className="rounded-2xl border border-white/10 bg-slate-950/60 px-4 py-3 transition hover:border-violet-300/30 hover:bg-slate-900"
                        >
                          <div className="text-xs uppercase tracking-[0.16em] text-slate-400">{item?.label}</div>
                          <div className="mt-1 text-sm font-medium text-white">{item?.status}</div>
                        </Link>
                      ))}
                  </div>

                  <div className="mt-5 flex items-center justify-between border-t border-white/10 pt-4">
                    <Link href={session.projectHref} className="inline-flex items-center text-sm font-medium text-violet-200 transition hover:text-white">
                      Open project
                      <BaseIcon path={mdiChevronRight} size={16} className="ml-1" />
                    </Link>
                    <div className="text-xs uppercase tracking-[0.16em] text-slate-500">Studio pipeline live</div>
                  </div>
                </div>
              ))}
            </div>
          ) : (
            <div className="rounded-2xl border border-dashed border-white/10 bg-white/5 p-8 text-center text-sm text-slate-300">
              No studio sessions yet. Launch your first beat-to-master workflow above and it will appear here instantly.
            </div>
          )}
        </CardBox>
      </SectionMain>
    </>
  );
};

StudioPage.getLayout = function getLayout(page: ReactElement) {
  return <LayoutAuthenticated permission={'READ_PROJECTS'}>{page}</LayoutAuthenticated>;
};

export default StudioPage;
