import json
import os
import time
from .audit import audit_tool_call
import subprocess
from typing import List, Any

import pandas as pd
from openpyxl import load_workbook, Workbook
from openpyxl.utils import range_boundaries
from openpyxl.worksheet.table import Table, TableStyleInfo


def open_workbook(path: str):
    _t = time.time()
    wb = load_workbook(path)
    wb.close()
    out = {"path": path, "sheets": wb.sheetnames}
    audit_tool_call("tool_spreadsheet.open_workbook", {"path": path}, {"ok": True}, True, int((time.time()-_t)*1000))
    return out


def read_range(path: str, sheet: str, a1_range: str):
    wb = load_workbook(path, data_only=True)
    ws = wb[sheet]
    min_col, min_row, max_col, max_row = range_boundaries(a1_range)
    data = []
    for row in ws.iter_rows(min_row=min_row, max_row=max_row, min_col=min_col, max_col=max_col, values_only=True):
        data.append(list(row))
    wb.close()
    return {"sheet": sheet, "range": a1_range, "values": data}


def write_range(path: str, sheet: str, start_cell: str, values: List[List[Any]], style: dict | None = None):
    wb = load_workbook(path)
    ws = wb[sheet]
    start_col = ws[start_cell].column
    start_row = ws[start_cell].row
    for r_idx, row in enumerate(values):
        for c_idx, val in enumerate(row):
            ws.cell(row=start_row + r_idx, column=start_col + c_idx, value=val)
    wb.save(path)
    wb.close()
    return {"status": "ok"}


def add_sheet(path: str, name: str):
    wb = load_workbook(path)
    if name in wb.sheetnames:
        wb.close()
        return {"status": "exists"}
    wb.create_sheet(title=name)
    wb.save(path)
    wb.close()
    return {"status": "ok"}


def create_workbook(path: str, template_spec_json: dict):
    wb = Workbook()
    wb.remove(wb.active)
    for sheet_spec in template_spec_json.get("sheets", []):
        ws = wb.create_sheet(title=sheet_spec.get("name", "Sheet"))
        data = sheet_spec.get("data", [])
        for row in data:
            ws.append(row)
    wb.save(path)
    wb.close()
    return {"status": "ok", "path": path}


def apply_table(path: str, sheet: str, a1_range: str, table_name: str):
    wb = load_workbook(path)
    ws = wb[sheet]
    table = Table(displayName=table_name, ref=a1_range)
    style = TableStyleInfo(name="TableStyleMedium9", showRowStripes=True)
    table.tableStyleInfo = style
    ws.add_table(table)
    wb.save(path)
    wb.close()
    return {"status": "ok"}


def validate(path: str):
    try:
        load_workbook(path).close()
        return []
    except Exception as e:
        return [str(e)]


def save_as(path: str, out_path: str):
    wb = load_workbook(path)
    wb.save(out_path)
    wb.close()
    return {"status": "ok", "out_path": out_path}


def convert_to_pdf(path: str, out_pdf_path: str):
    cmd = ["soffice", "--headless", "--convert-to", "pdf", "--outdir", os.path.dirname(out_pdf_path), path]
    try:
        subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        return {"status": "ok", "out_pdf_path": out_pdf_path}
    except Exception as e:
        return {"status": "error", "error": str(e)}
