"""Recordings screen — list MP3s, play, transcribe, summarize, rename, delete, favorite."""

from __future__ import annotations

import re
import subprocess
import threading
import time
from pathlib import Path
from typing import TYPE_CHECKING

import flet as ft

from meeting_helper.flet_gui.components.audio_player import AudioPlayer

if TYPE_CHECKING:
    from meeting_helper.config import Config

TEAL = "#4ec9b0"
ERROR_RED = "#f14c4c"
HIGHLIGHT_BG = ft.Colors.PRIMARY_CONTAINER


def _format_duration(mp3: Path) -> str:
    try:
        result = subprocess.run(
            ["ffprobe", "-v", "quiet", "-show_entries", "format=duration",
             "-of", "default=noprint_wrappers=1:nokey=1", str(mp3)],
            capture_output=True, text=True, timeout=3,
        )
        if result.returncode == 0:
            secs = float(result.stdout.strip())
            mins, s = divmod(int(secs), 60)
            hrs, mins = divmod(mins, 60)
            return f"{hrs}:{mins:02d}:{s:02d}" if hrs else f"{mins}:{s:02d}"
    except Exception:
        pass
    return "—"


def _clean_name(stem: str) -> str:
    parts = stem.split("_", 2)
    if len(parts) >= 2 and len(parts[0]) == 10 and "-" in parts[0]:
        rest = "_".join(parts[2:]) if len(parts) > 2 else stem
        return rest.replace("_", " ") or stem
    return stem.replace("_", " ")


def _timestamp_prefix(stem: str) -> str:
    parts = stem.split("_", 2)
    if len(parts) >= 2 and len(parts[0]) == 10 and "-" in parts[0]:
        return f"{parts[0]}_{parts[1]}_"
    return ""


def _parse_lines_with_times(text: str) -> list[tuple[float, str]]:
    """Parse transcript lines into (seconds, text). Lines without timestamps get -1."""
    entries = []
    for line in text.split("\n"):
        stripped = line.strip()
        if not stripped:
            entries.append((-1, ""))
            continue
        m = re.match(r"\[?(\d{1,2}):(\d{2}):(\d{2})\]?\s*(.*)", stripped)
        if m:
            h, mi, s = int(m.group(1)), int(m.group(2)), int(m.group(3))
            entries.append((h * 3600 + mi * 60 + s, stripped))
            continue
        m = re.match(r"\[?(\d{1,2}):(\d{2})\]?\s*(.*)", stripped)
        if m:
            mi, s = int(m.group(1)), int(m.group(2))
            entries.append((mi * 60 + s, stripped))
            continue
        entries.append((-1, stripped))
    return entries


class RecordingsScreen(ft.Column):
    """Browse recordings, play audio, transcribe, summarize, rename, delete, favorite."""

    def __init__(self, page: ft.Page, config: "Config"):
        super().__init__(expand=True, spacing=0)
        self._page = page
        self._config = config
        self._raw_config = config
        self._app_config = config.to_app_config()
        self._recordings_dir = Path(config.recordings_dir)
        self._mp3s: list[Path] = []
        self._current_mp3: Path | None = None
        self._rows: list[ft.DataRow] = []
        self._transcript_lines: list[tuple[float, str]] = []
        self._transcript_controls: list[ft.Container] = []
        self._last_highlight_idx = -1

        # --- Header ---
        refresh_btn = ft.IconButton(
            icon=ft.Icons.REFRESH,
            tooltip="Refresh",
            on_click=lambda e: self._refresh(),
        )

        # --- Data table ---
        self._table = ft.DataTable(
            columns=[
                ft.DataColumn(ft.Text("", size=12), numeric=False),
                ft.DataColumn(ft.Text("Name", size=13)),
                ft.DataColumn(ft.Text("Duration", size=13), numeric=True),
                ft.DataColumn(ft.Text("Date", size=13), numeric=True),
                ft.DataColumn(ft.Text("", size=12)),
            ],
            rows=[],
            column_spacing=16,
            horizontal_lines=ft.BorderSide(1, ft.Colors.OUTLINE_VARIANT),
            heading_row_height=40,
            data_row_min_height=44,
            data_row_max_height=44,
            expand=True,
        )

        # --- Detail panel ---
        self._transcribe_btn = ft.ElevatedButton(
            "Transcribe",
            icon=ft.Icons.MIC,
            on_click=self._do_transcribe,
            disabled=True,
        )
        self._summarize_btn = ft.ElevatedButton(
            "Summarize",
            icon=ft.Icons.SUMMARIZE,
            on_click=self._do_summarize,
            disabled=True,
        )
        self._status_label = ft.Text("", size=12, color=ft.Colors.ON_SURFACE_VARIANT)

        self._player = AudioPlayer(page, on_position_change=self._on_player_position)

        self._transcript_title = ft.Text("", size=14, weight=ft.FontWeight.W_600, visible=False)
        self._transcript_column = ft.Column(spacing=0, scroll=ft.ScrollMode.AUTO)
        self._transcript_container = ft.Container(
            content=self._transcript_column,
            expand=True,
            border=ft.border.all(1, ft.Colors.OUTLINE_VARIANT),
            border_radius=8,
            padding=12,
        )

        # --- Dialogs ---
        self._rename_field = ft.TextField(label="New name", dense=True, autofocus=True)
        self._rename_dialog = ft.AlertDialog(
            title=ft.Text("Rename Recording"),
            content=self._rename_field,
            actions=[
                ft.TextButton("Cancel", on_click=self._close_dialog),
                ft.ElevatedButton("Rename", on_click=self._confirm_rename),
            ],
        )
        self._delete_dialog = ft.AlertDialog(
            title=ft.Text("Delete Recording"),
            content=ft.Text(""),
            actions=[
                ft.TextButton("Cancel", on_click=self._close_dialog),
                ft.ElevatedButton("Delete", bgcolor=ERROR_RED, color="white", on_click=self._confirm_delete),
            ],
        )
        page.overlay.extend([self._rename_dialog, self._delete_dialog])

        self.controls = [
            ft.Container(
                content=ft.Column([
                    ft.Row([
                        ft.Text("Recordings", size=22, weight=ft.FontWeight.W_600),
                        refresh_btn,
                    ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN),
                    ft.Container(
                        content=ft.Column([self._table], scroll=ft.ScrollMode.AUTO,
                                          horizontal_alignment=ft.CrossAxisAlignment.STRETCH),
                        expand=2,
                        border=ft.border.all(1, ft.Colors.OUTLINE_VARIANT),
                        border_radius=8,
                    ),
                    ft.Row([self._transcribe_btn, self._summarize_btn, self._status_label], spacing=12),
                    self._player,
                    self._transcript_title,
                    self._transcript_container,
                ], spacing=12, expand=True, horizontal_alignment=ft.CrossAxisAlignment.STRETCH),
                padding=30,
                expand=True,
            ),
        ]

    def on_activate(self):
        if not self._rows:
            self._refresh()

    def cleanup(self):
        """Stop audio playback — called on app exit."""
        self._player.stop()

    def _refresh(self):
        self._table.rows.clear()
        self._rows.clear()
        if not self._recordings_dir.is_dir():
            self._page.update()
            return

        self._mp3s = sorted(
            self._recordings_dir.glob("*.mp3"),
            key=lambda p: p.stat().st_mtime,
            reverse=True,
        )

        for idx, mp3 in enumerate(self._mp3s):
            is_fav = self._raw_config.is_favorite(mp3.name)
            has_transcript = mp3.with_suffix(".transcript.txt").exists()
            display = _clean_name(mp3.stem)
            mtime = mp3.stat().st_mtime
            date_str = time.strftime("%Y-%m-%d %H:%M", time.localtime(mtime))
            row_idx = idx

            row = ft.DataRow(
                cells=[
                    ft.DataCell(
                        ft.IconButton(
                            icon=ft.Icons.STAR if is_fav else ft.Icons.STAR_BORDER,
                            icon_color="#dcdcaa" if is_fav else ft.Colors.OUTLINE,
                            icon_size=18,
                            on_click=lambda e, i=row_idx: self._toggle_favorite(i),
                            data=row_idx,
                        ),
                    ),
                    ft.DataCell(
                        ft.Text(
                            display,
                            size=13,
                            color="#3fb950" if has_transcript else None,
                        ),
                    ),
                    ft.DataCell(ft.Text("...", size=13, color=ft.Colors.ON_SURFACE_VARIANT)),
                    ft.DataCell(ft.Text(date_str, size=13, color=ft.Colors.ON_SURFACE_VARIANT)),
                    ft.DataCell(
                        ft.PopupMenuButton(
                            icon=ft.Icons.MORE_VERT,
                            icon_size=18,
                            items=[
                                ft.PopupMenuItem(content=ft.Text("Transcribe"), icon=ft.Icons.MIC,
                                                 on_click=lambda e, i=row_idx: self._select_and_transcribe(i)),
                                ft.PopupMenuItem(content=ft.Text("Rename"), icon=ft.Icons.EDIT,
                                                 on_click=lambda e, i=row_idx: self._start_rename(i)),
                                ft.PopupMenuItem(content=ft.Text("Delete"), icon=ft.Icons.DELETE,
                                                 on_click=lambda e, i=row_idx: self._start_delete(i)),
                            ],
                        ),
                    ),
                ],
                on_select_change=lambda e, i=row_idx: self._on_row_selected(i),
            )
            self._rows.append(row)
            self._table.rows.append(row)

        self._page.update()

        mp3s_snapshot = list(self._mp3s)
        self._page.run_thread(self._load_durations, mp3s_snapshot)

    def _load_durations(self, mp3s: list[Path]):
        for idx, mp3 in enumerate(mp3s):
            dur = _format_duration(mp3)
            if idx < len(self._rows):
                self._rows[idx].cells[2].content.value = dur
        try:
            self._page.update()
        except Exception:
            pass

    def _on_row_selected(self, idx: int):
        if idx < 0 or idx >= len(self._mp3s):
            return
        mp3 = self._mp3s[idx]
        self._current_mp3 = mp3
        self._player.load(mp3)
        self._transcribe_btn.disabled = False
        self._status_label.value = ""

        summary_path = mp3.with_suffix(".summary.txt")
        transcript_path = mp3.with_suffix(".transcript.txt")
        live_path = mp3.with_suffix(".live.txt")

        if summary_path.exists():
            self._load_transcript_view(summary_path)
            self._summarize_btn.disabled = True
        elif transcript_path.exists():
            self._load_transcript_view(transcript_path)
            self._summarize_btn.disabled = False
        elif live_path.exists():
            self._load_transcript_view(live_path)
            self._summarize_btn.disabled = True
        else:
            self._transcript_title.visible = False
            self._transcript_column.controls.clear()
            self._transcript_lines.clear()
            self._transcript_controls.clear()
            self._summarize_btn.disabled = True

        self._page.update()

    def _load_transcript_view(self, path: Path):
        """Load transcript into individual line containers for highlighting."""
        self._transcript_title.value = path.name
        self._transcript_title.visible = True
        text = path.read_text()
        self._transcript_lines = _parse_lines_with_times(text)
        self._transcript_controls.clear()
        self._transcript_column.controls.clear()
        self._last_highlight_idx = -1

        for idx, (ts, line) in enumerate(self._transcript_lines):
            container = ft.Container(
                content=ft.Text(
                    line,
                    size=13,
                    selectable=True,
                    font_family="Menlo, Monaco, Courier New, monospace",
                ),
                padding=ft.padding.symmetric(horizontal=4, vertical=2),
                border_radius=4,
                key=f"tline_{idx}",
            )
            self._transcript_controls.append(container)
            self._transcript_column.controls.append(container)

    def _on_player_position(self, position_secs: float):
        """Highlight the transcript line closest to current playback position."""
        if not self._transcript_lines or not self._transcript_controls:
            return

        # Find the last line with timestamp <= current position
        best_idx = -1
        for i, (ts, _) in enumerate(self._transcript_lines):
            if ts < 0:
                continue
            if ts <= position_secs:
                best_idx = i
            else:
                break

        if best_idx == self._last_highlight_idx:
            return

        # Remove old highlight
        if 0 <= self._last_highlight_idx < len(self._transcript_controls):
            self._transcript_controls[self._last_highlight_idx].bgcolor = None

        # Apply new highlight and auto-scroll
        if best_idx >= 0:
            self._transcript_controls[best_idx].bgcolor = HIGHLIGHT_BG
            # ~22px per line, keep highlighted line near top third of view
            offset = max(0, best_idx * 22 - 60)

            async def _scroll():
                try:
                    await self._transcript_column.scroll_to(offset=offset, duration=200)
                except Exception:
                    pass

            self._page.run_task(_scroll)

        self._last_highlight_idx = best_idx

    def _toggle_favorite(self, idx: int):
        if idx < 0 or idx >= len(self._mp3s):
            return
        mp3 = self._mp3s[idx]
        if self._raw_config.is_favorite(mp3.name):
            self._raw_config.remove_favorite(mp3.name)
        else:
            self._raw_config.add_favorite(mp3.name)
        self._refresh()

    def _select_and_transcribe(self, idx: int):
        self._on_row_selected(idx)
        self._do_transcribe(None)

    def _start_rename(self, idx: int):
        if idx < 0 or idx >= len(self._mp3s):
            return
        self._rename_target_idx = idx
        self._rename_field.value = _clean_name(self._mp3s[idx].stem)
        self._rename_dialog.open = True
        self._page.update()

    def _confirm_rename(self, e):
        idx = self._rename_target_idx
        mp3 = self._mp3s[idx]
        new_name = (self._rename_field.value or "").strip().replace(" ", "_")
        if not new_name:
            return

        prefix = _timestamp_prefix(mp3.stem)
        new_stem = f"{prefix}{new_name}" if prefix else new_name
        new_mp3 = mp3.parent / f"{new_stem}.mp3"

        if new_mp3.exists():
            self._status_label.value = "A file with that name already exists."
            self._status_label.color = ERROR_RED
            self._rename_dialog.open = False
            self._page.update()
            return

        try:
            for suffix in (".mp3", ".transcript.txt", ".summary.txt", ".live.txt"):
                old = mp3.parent / f"{mp3.stem}{suffix}"
                if old.exists():
                    old.rename(mp3.parent / f"{new_stem}{suffix}")
            if self._raw_config.is_favorite(mp3.name):
                self._raw_config.remove_favorite(mp3.name)
                self._raw_config.add_favorite(new_mp3.name)
            self._status_label.value = f"Renamed to: {new_name}"
            self._status_label.color = TEAL
        except Exception as exc:
            self._status_label.value = f"Error: {exc}"
            self._status_label.color = ERROR_RED

        self._rename_dialog.open = False
        self._refresh()

    def _start_delete(self, idx: int):
        if idx < 0 or idx >= len(self._mp3s):
            return
        self._delete_target_idx = idx
        mp3 = self._mp3s[idx]
        name = _clean_name(mp3.stem)
        files = [f for f in [
            mp3,
            mp3.with_suffix(".transcript.txt"),
            mp3.with_suffix(".summary.txt"),
            mp3.with_suffix(".live.txt"),
        ] if f.exists()]
        self._delete_dialog.content = ft.Text(
            f"Delete '{name}'?\n\nThis will permanently remove {len(files)} file(s)."
        )
        self._delete_dialog.open = True
        self._page.update()

    def _confirm_delete(self, e):
        idx = self._delete_target_idx
        mp3 = self._mp3s[idx]
        files = [f for f in [
            mp3,
            mp3.with_suffix(".transcript.txt"),
            mp3.with_suffix(".summary.txt"),
            mp3.with_suffix(".live.txt"),
        ] if f.exists()]

        try:
            for f in files:
                f.unlink()
            self._raw_config.remove_favorite(mp3.name)
            self._current_mp3 = None
            self._player.load(None)
            self._transcript_title.visible = False
            self._transcript_column.controls.clear()
            self._transcript_controls.clear()
            self._transcript_lines.clear()
            self._transcribe_btn.disabled = True
            self._summarize_btn.disabled = True
            name = _clean_name(mp3.stem)
            self._status_label.value = f"Deleted: {name}"
            self._status_label.color = TEAL
        except Exception as exc:
            self._status_label.value = f"Error: {exc}"
            self._status_label.color = ERROR_RED

        self._delete_dialog.open = False
        self._refresh()

    def _close_dialog(self, e):
        self._rename_dialog.open = False
        self._delete_dialog.open = False
        self._page.update()

    def _do_transcribe(self, e):
        if not self._current_mp3:
            return
        self._transcribe_btn.disabled = True
        self._summarize_btn.disabled = True
        self._status_label.value = "Transcribing..."
        self._status_label.color = "#dcdcaa"
        self._page.update()

        mp3 = self._current_mp3
        app_config = self._app_config

        def _work():
            try:
                from meeting_helper.ai.client import transcribe_audio_file
                result = transcribe_audio_file(str(mp3), app_config)
                self._transcript_title.value = "Transcript"
                self._transcript_title.visible = True
                # Reload as structured transcript
                transcript_path = mp3.with_suffix(".transcript.txt")
                if transcript_path.exists():
                    self._load_transcript_view(transcript_path)
                else:
                    self._transcript_column.controls.clear()
                    self._transcript_column.controls.append(
                        ft.Text(result, size=13, selectable=True)
                    )
                self._status_label.value = "Transcription complete"
                self._status_label.color = TEAL
                self._summarize_btn.disabled = False
            except Exception as exc:
                self._status_label.value = f"Error: {exc}"
                self._status_label.color = ERROR_RED
            finally:
                self._transcribe_btn.disabled = False
                try:
                    self._page.update()
                except Exception:
                    pass

        self._page.run_thread(_work)

    def _do_summarize(self, e):
        if not self._current_mp3:
            return
        mp3 = self._current_mp3
        transcript_path = mp3.with_suffix(".transcript.txt")
        if not transcript_path.exists():
            live_path = mp3.with_suffix(".live.txt")
            if live_path.exists():
                transcript_path = live_path
            else:
                self._status_label.value = "No transcript to summarize"
                self._page.update()
                return

        self._summarize_btn.disabled = True
        self._status_label.value = "Summarizing..."
        self._status_label.color = "#dcdcaa"
        self._page.update()

        app_config = self._app_config

        def _work():
            try:
                import asyncio
                from meeting_helper.ai.client import summarize_transcript
                result = asyncio.run(summarize_transcript(str(transcript_path), app_config))
                summary_path = mp3.with_suffix(".summary.txt")
                if summary_path.exists():
                    self._load_transcript_view(summary_path)
                else:
                    self._transcript_title.value = "Summary"
                    self._transcript_title.visible = True
                    self._transcript_column.controls.clear()
                    self._transcript_column.controls.append(
                        ft.Text(result, size=13, selectable=True)
                    )
                self._status_label.value = "Summary complete"
                self._status_label.color = TEAL
            except Exception as exc:
                self._status_label.value = f"Error: {exc}"
                self._status_label.color = ERROR_RED
                self._summarize_btn.disabled = False
            try:
                self._page.update()
            except Exception:
                pass

        self._page.run_thread(_work)
