from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

from youtube_cli_agent.errors import ToolExecutionError, ValidationError
from youtube_cli_agent.models import PersistResult, TranscriptResult, VideoMetadata
from youtube_cli_agent.normalize import build_markdown_filename


@dataclass(slots=True)
class MarkdownPersistenceTool:
    min_transcript_chars: int = 80

    def target_path(self, output_dir: Path, metadata: VideoMetadata) -> Path:
        filename = build_markdown_filename(metadata.title, metadata.channel)
        return output_dir / filename

    def run(
        self,
        output_dir: Path,
        metadata: VideoMetadata,
        transcript: TranscriptResult,
        *,
        overwrite: bool = False,
    ) -> PersistResult:
        output_dir.mkdir(parents=True, exist_ok=True)
        target = self.target_path(output_dir, metadata)

        if target.exists() and not overwrite:
            return PersistResult(path=target, skipped=True, reason="File already exists and overwrite is disabled.")

        body = self._build_markdown(metadata, transcript)
        temp = target.with_suffix(target.suffix + ".tmp")
        try:
            temp.write_text(body, encoding="utf-8")
            temp.replace(target)
        except Exception as exc:
            raise ToolExecutionError(
                code="WRITE_FAILED",
                stage="Markdown Persistence",
                message=f"Failed to write markdown file: {exc}",
            ) from None

        self._validate_written_file(target, transcript)
        return PersistResult(path=target, skipped=False, reason="Markdown file written successfully.")

    def _validate_written_file(self, path: Path, transcript: TranscriptResult) -> None:
        if not path.exists() or not path.is_file():
            raise ValidationError(
                code="FILE_NOT_WRITTEN",
                stage="Markdown Persistence",
                message="Markdown file does not exist after write operation.",
            )

        content = path.read_text(encoding="utf-8")
        normalized_transcript = " ".join(transcript.text.split())
        if len(normalized_transcript) < self.min_transcript_chars:
            raise ValidationError(
                code="TRANSCRIPT_TOO_SHORT",
                stage="Markdown Persistence",
                message="Transcript is below minimum threshold before file verification.",
            )

        if normalized_transcript not in " ".join(content.split()):
            raise ValidationError(
                code="TRANSCRIPT_TRUNCATED",
                stage="Markdown Persistence",
                message="Transcript text appears truncated in written file.",
            )

        required_tokens = [
            "# ",
            "- Channel:",
            "- Video URL:",
            "- Publish Date:",
            "- Duration:",
            "## Description",
            "## Transcript",
            "- Transcript Source:",
            "- Generated At (UTC):",
        ]
        missing = [token for token in required_tokens if token not in content]
        if missing:
            raise ValidationError(
                code="FILE_INTEGRITY_FAILED",
                stage="Markdown Persistence",
                message=f"Written file is missing required sections: {', '.join(missing)}",
            )

    @staticmethod
    def _format_duration(seconds: int) -> str:
        hours = seconds // 3600
        minutes = (seconds % 3600) // 60
        secs = seconds % 60
        if hours:
            return f"{hours:02d}:{minutes:02d}:{secs:02d}"
        return f"{minutes:02d}:{secs:02d}"

    def _build_markdown(self, metadata: VideoMetadata, transcript: TranscriptResult) -> str:
        duration_text = self._format_duration(metadata.duration_seconds)
        generated_at = transcript.generated_at.strftime("%Y-%m-%dT%H:%M:%SZ")

        description = metadata.description.strip() or "No description provided."
        transcript_text = transcript.text.strip()

        return (
            f"# {metadata.title}\n\n"
            f"- Channel: {metadata.channel}\n"
            f"- Video URL: {metadata.url}\n"
            f"- Publish Date: {metadata.publish_date}\n"
            f"- Duration: {duration_text}\n\n"
            f"## Description\n\n"
            f"{description}\n\n"
            f"## Transcript\n\n"
            f"{transcript_text}\n\n"
            f"## Metadata\n\n"
            f"- Transcript Source: {transcript.source}\n"
            f"- Transcript Language: {transcript.language}\n"
            f"- Generated At (UTC): {generated_at}\n"
        )
