from __future__ import annotations

from dataclasses import dataclass, field
from pathlib import Path

from neurobyte.io.ipython_reader import read_ipython_code_cells
from neurobyte.io.nb_reader import Cell, read_ipynb_cells
from neurobyte.render.text import render_json, render_txt


@dataclass(frozen=True)
class ExportOptions:
    include_markdown: bool = False
    redact_secrets: bool = True
    max_cells: int | None = None
    cell_indices: list[int] | None = None
    extra_redact_patterns: list[str] = field(default_factory=list)
    output_format: str = "txt"  # "txt" or "json"


def export_notebook(
    notebook_path: str | Path,
    out_path: str | Path | None = None,
    *,
    options: ExportOptions | None = None,
) -> Path:
    opts = options or ExportOptions()
    nb_path = Path(notebook_path).expanduser().resolve()

    # Read cells with new API
    cells = read_ipynb_cells(
        nb_path,
        include_markdown=opts.include_markdown,
        cell_indices=opts.cell_indices,
    )

    # Apply max_cells if specified
    if opts.max_cells is not None:
        cells = cells[: opts.max_cells]

    # Render
    if opts.output_format == "json":
        output = render_json(
            cells,
            redact_secrets=opts.redact_secrets,
            extra_redact_patterns=list(opts.extra_redact_patterns),
        )
        default_suffix = ".neurobyte.json"
    else:
        output = render_txt(
            cells,
            redact_secrets=opts.redact_secrets,
            extra_redact_patterns=list(opts.extra_redact_patterns),
        )
        default_suffix = ".neurobyte.txt"

    out = (
        Path(out_path).expanduser().resolve()
        if out_path is not None
        else nb_path.with_suffix(default_suffix)
    )
    out.write_text(output, encoding="utf-8")
    return out


def export_here(
    out_path: str | Path = "neurobyte_export.txt",
    *,
    options: ExportOptions | None = None,
) -> Path:
    """
    Best-effort export from inside a live Jupyter/IPython session.

    Note: IPython history can be incomplete depending on environment/settings.
    For reliability, prefer export_notebook(<path.ipynb>).
    """
    opts = options or ExportOptions()
    code_cells = read_ipython_code_cells(max_cells=opts.max_cells)

    # Convert to Cell objects
    cells = [
        Cell(cell_type="code", content=c, index=i + 1) for i, c in enumerate(code_cells)
    ]

    # Apply cell indices filter
    if opts.cell_indices:
        cells = [c for c in cells if c.index in opts.cell_indices]

    # Render
    if opts.output_format == "json":
        output = render_json(
            cells,
            redact_secrets=opts.redact_secrets,
            extra_redact_patterns=list(opts.extra_redact_patterns),
        )
    else:
        output = render_txt(
            cells,
            redact_secrets=opts.redact_secrets,
            extra_redact_patterns=list(opts.extra_redact_patterns),
        )

    out = Path(out_path).expanduser().resolve()
    out.write_text(output, encoding="utf-8")
    return out
