import os
import re
import markdown
from pathlib import Path
from fastapi import APIRouter, Request, Depends, Form
from fastapi.responses import HTMLResponse, RedirectResponse
from sqlalchemy.ext.asyncio import AsyncSession
from app.database import get_db
from datetime import datetime
from app.config import get_settings
from app.services.docs_permissions import load_permissions, save_permissions, discover_docs, can_access_doc, get_allowed_docs
from app.dependencies import get_current_user, require_role

settings = get_settings()
router = APIRouter(prefix="/service/documents", tags=["documents"])
from app.templating import templates


def now_str():
    return datetime.now().strftime("%d.%m.%Y %H:%M")


def _doc_ctx(request, user, **kw):
    original_user = request.session.get("original_user")
    available_roles = {"owner": ["owner", "engineer", "technician"], "engineer": ["engineer", "technician"]}
    c = {"request": request, "user": user, "now": now_str(),
         "role_permissions": getattr(request.state, 'role_permissions', {}),
         "role_override_active": original_user is not None,
         "original_role": original_user["role"] if original_user else None,
         "available_roles": available_roles.get(user["role"], [user["role"]]) if user else []}
    c.update(kw)
    return c


def transliterate_slug(text: str) -> str:
    translit_map = {
        'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo', 'ж': 'zh',
        'з': 'z', 'и': 'i', 'й': 'y', 'к': 'k', 'л': 'l', 'м': 'm', 'н': 'n', 'о': 'o',
        'п': 'p', 'р': 'r', 'с': 's', 'т': 't', 'у': 'u', 'ф': 'f', 'х': 'kh', 'ц': 'ts',
        'ч': 'ch', 'ш': 'sh', 'щ': 'shch', 'ъ': '', 'ы': 'y', 'ь': '', 'э': 'e', 'ю': 'yu',
        'я': 'ya', ' ': '_',
    }
    result = ''.join(translit_map.get(c.lower(), c) for c in text)
    result = re.sub(r'[^a-zA-Z0-9_\-]', '', result)
    result = re.sub(r'_+', '_', result)
    return result.strip('_').lower()


def render_markdown(content: str) -> str:
    md = markdown.Markdown(extensions=['tables', 'fenced_code', 'toc', 'attr_list'])
    return md.convert(content)


@router.get("/")
async def documents_list(
    request: Request,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    docs = get_allowed_docs(user["role"])
    return templates.TemplateResponse("documents/list.html", _doc_ctx(request, user, docs=docs))


@router.get("/admin/permissions")
async def permissions_page(
    request: Request,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    if user["role"] != "owner":
        return HTMLResponse(content="Доступ запрещён", status_code=403)

    perms = discover_docs()
    return templates.TemplateResponse("documents/permissions.html", _doc_ctx(request, user, perms=perms))


@router.post("/admin/permissions")
async def permissions_update(
    request: Request,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    if user["role"] != "owner":
        return HTMLResponse(content="Доступ запрещён", status_code=403)

    form = await request.form()
    perms = discover_docs()

    for slug in perms.keys():
        engineer_view = form.get(f"{slug}_engineer_view") == "on"
        engineer_edit = form.get(f"{slug}_engineer_edit") == "on"
        technician_view = form.get(f"{slug}_technician_view") == "on"

        if engineer_edit and not engineer_view:
            engineer_view = True

        perms[slug]["permissions"]["engineer"] = {
            "view": engineer_view,
            "edit": engineer_edit,
            "cancel": engineer_edit,
        }
        perms[slug]["permissions"]["technician"] = {
            "view": technician_view,
        }

    save_permissions(perms)
    return RedirectResponse(url="/service/documents/admin/permissions", status_code=302)


@router.post("/admin/create")
async def document_create(
    request: Request,
    title: str = Form(...),
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    if user["role"] != "owner":
        return HTMLResponse(content="Доступ запрещён", status_code=403)

    slug = transliterate_slug(title)
    if not slug:
        return HTMLResponse(content="Некорректное название", status_code=400)

    docs_dir = settings.DOCS_DIR
    os.makedirs(docs_dir, exist_ok=True)
    filename = f"{slug}.md"
    filepath = os.path.join(docs_dir, filename)

    if os.path.exists(filepath):
        return HTMLResponse(content="Документ уже существует", status_code=400)

    with open(filepath, "w", encoding="utf-8") as f:
        f.write(f"# {title}\n\n")

    perms = load_permissions()
    perms[slug] = {
        "title": title,
        "filename": filename,
        "sort_order": len(perms),
        "permissions": {
            "engineer": {"view": False, "edit": False, "cancel": False},
            "technician": {"view": False},
        },
    }
    save_permissions(perms)

    return RedirectResponse(url=f"/service/documents/{slug}/edit", status_code=302)


@router.get("/tech-access")
async def tech_access_page(
    request: Request,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    if user["role"] != "engineer":
        return HTMLResponse(content="Доступ только для инженеров", status_code=403)

    perms = discover_docs()
    editable_docs = [
        doc for slug, doc in perms.items()
        if doc.get("permissions", {}).get("engineer", {}).get("edit", False)
    ]
    return templates.TemplateResponse("documents/tech_access.html", _doc_ctx(request, user, docs=editable_docs, perms=perms))


@router.post("/tech-access")
async def tech_access_update(
    request: Request,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    if user["role"] != "engineer":
        return HTMLResponse(content="Доступ только для инженеров", status_code=403)

    form = await request.form()
    perms = discover_docs()

    for slug in perms.keys():
        if not perms[slug].get("permissions", {}).get("engineer", {}).get("edit", False):
            continue
        technician_view = form.get(f"{slug}_technician_view") == "on"
        perms[slug]["permissions"]["technician"] = {"view": technician_view}

    save_permissions(perms)
    return RedirectResponse(url="/service/documents/tech-access", status_code=302)


@router.get("/{slug}")
async def document_view(
    slug: str,
    request: Request,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    if not can_access_doc(user["role"], slug, "view"):
        return HTMLResponse(content="Доступ запрещён", status_code=403)

    docs_dir = settings.DOCS_DIR
    perms = discover_docs()
    doc = perms.get(slug)
    if not doc:
        return HTMLResponse(content="Документ не найден", status_code=404)

    filepath = os.path.join(docs_dir, doc["filename"])
    if not os.path.exists(filepath):
        return HTMLResponse(content="Файл не найден", status_code=404)

    with open(filepath, "r", encoding="utf-8") as f:
        content = f.read()

    html_content = render_markdown(content)
    return templates.TemplateResponse("documents/view.html", _doc_ctx(request, user,
        doc=doc, content=html_content,
        can_edit=can_access_doc(user["role"], slug, "edit"),
        can_download=user["role"] == "owner",
    ))


@router.get("/{slug}/edit")
async def document_edit(
    slug: str,
    request: Request,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    if not can_access_doc(user["role"], slug, "edit"):
        return HTMLResponse(content="Доступ запрещён", status_code=403)

    docs_dir = settings.DOCS_DIR
    perms = discover_docs()
    doc = perms.get(slug)
    if not doc:
        return HTMLResponse(content="Документ не найден", status_code=404)

    filepath = os.path.join(docs_dir, doc["filename"])
    if not os.path.exists(filepath):
        return HTMLResponse(content="Файл не найден", status_code=404)

    with open(filepath, "r", encoding="utf-8") as f:
        content = f.read()

    return templates.TemplateResponse("documents/edit.html", _doc_ctx(request, user, doc=doc, content=content))


@router.post("/{slug}/edit")
async def document_update(
    slug: str,
    request: Request,
    content: str = Form(...),
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    if not can_access_doc(user["role"], slug, "edit"):
        return HTMLResponse(content="Доступ запрещён", status_code=403)

    docs_dir = settings.DOCS_DIR
    perms = discover_docs()
    doc = perms.get(slug)
    if not doc:
        return HTMLResponse(content="Документ не найден", status_code=404)

    filepath = os.path.join(docs_dir, doc["filename"])
    with open(filepath, "w", encoding="utf-8") as f:
        f.write(content)

    return RedirectResponse(url=f"/service/documents/{slug}", status_code=302)


@router.get("/{slug}/download")
async def document_download(
    slug: str,
    request: Request,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    if user["role"] != "owner":
        return HTMLResponse(content="Скачивание доступно только владельцу", status_code=403)

    from fastapi.responses import FileResponse
    docs_dir = settings.DOCS_DIR
    perms = discover_docs()
    doc = perms.get(slug)
    if not doc:
        return HTMLResponse(content="Документ не найден", status_code=404)

    filepath = os.path.join(docs_dir, doc["filename"])
    if not os.path.exists(filepath):
        return HTMLResponse(content="Файл не найден", status_code=404)

    return FileResponse(filepath, filename=doc["filename"], media_type="text/markdown")
