from __future__ import annotations

import enum
import uuid
from dataclasses import dataclass
from functools import cache, partial

import file_widgets
import pydantic
import user
from PyQt6.QtWidgets import (
    QComboBox,
    QHBoxLayout,
    QLabel,
    QLineEdit,
    QMessageBox,
    QPushButton,
    QVBoxLayout,
    QWidget,
)
from request_client import RequestClient


class Permission(enum.StrEnum):
    read = enum.auto()
    write = enum.auto()
    manage = enum.auto()

    def set(self, folder_id: uuid.UUID, user_id: int):
        response = RequestClient().client.post(
            "/permissions",
            json={
                "folder_id": str(folder_id),
                "permission_type": str(self),
                "user_id": int(user_id),
            },
        )
        if not response.is_success:
            QMessageBox.warning(None, "Error setting permissions", response.text)

    @staticmethod
    def delete(folder_id: uuid.UUID, user_id: int, widget: FolderInfoWidget):
        response = RequestClient().client.delete(
            "/permissions",
            params={
                "folder_id": folder_id,
                "user_id": user_id,
            },
        )
        if not response.is_success:
            QMessageBox.warning(None, "Error deleting permissions", response.text)
        else:
            widget.redraw()


@dataclass(slots=True)
class Permissions:
    mapping: dict[int, Permission]

    @staticmethod
    def get(folder_id: uuid.UUID) -> Permissions:
        mapping = pydantic.TypeAdapter(dict[str, Permission]).validate_json(
            RequestClient()
            .client.get("/permissions", params={"folder_id": folder_id})
            .text
        )
        return Permissions(mapping)


class FolderInfoWidget(QWidget):
    def __init__(self, folder: file_widgets.Folder):
        super().__init__()
        self.setWindowTitle("Folder info")
        self.folder = folder
        self.user_cache = cache(user.User.get)
        self.user_mapping: dict[str, int] = {}
        self.redraw()

    def redraw(self):
        self.permissions = Permissions.get(self.folder.folder_id)
        main_layout = QVBoxLayout()

        owner_name = self.user_cache(self.folder.owner_id)
        main_layout.addWidget(
            QLabel(
                f"Owner: {owner_name}\n"
                + f"Folder name: {self.folder.folder_name}\n"
                + f"Created at: {self.folder.created_at}"
            )
        )
        for user_id, permissions in self.permissions.mapping.items():
            layout = QHBoxLayout()
            name = QLabel(self.user_cache(user_id).username)
            combo = QComboBox()
            combo.addItems(map(str, Permission))
            combo.setCurrentText(str(permissions))
            combo.currentTextChanged.connect(partial(self.change, user_id=user_id))
            delete = QPushButton("Delete")
            delete.clicked.connect(
                partial(Permission.delete, self.folder.folder_id, user_id, self)
            )
            layout.addWidget(name)
            layout.addWidget(combo)
            layout.addWidget(delete)
            main_layout.addLayout(layout)

        layout = QHBoxLayout()
        self.search_str = QLineEdit()
        layout.addWidget(self.search_str)
        search = QPushButton("Search")
        search.clicked.connect(self.search)
        layout.addWidget(search)
        main_layout.addLayout(layout)

        layout = QHBoxLayout()
        self.search_combo = QComboBox()
        self.perm_combo = QComboBox()
        self.perm_combo.addItems(map(str, Permission))
        button = QPushButton("+")
        button.clicked.connect(self.search_save)
        layout.addWidget(self.search_combo)
        layout.addWidget(self.perm_combo)
        layout.addWidget(button)
        main_layout.addLayout(layout)

        if self.layout():
            QWidget().setLayout(self.layout())
        self.setLayout(main_layout)

    def change(self, text: str, *, user_id: int):
        Permission(text).set(self.folder.folder_id, user_id)

    def search(self):
        result = user.UserSearch.search(self.search_str.text())
        self.search_combo.clear()
        self.user_mapping.clear()
        for item in result:
            self.user_mapping[item.username] = item.user_id
            self.search_combo.addItem(item.username)

    def search_save(self):
        permission = Permission(self.perm_combo.currentText())
        user_id = self.user_mapping[self.search_combo.currentText()]
        permission.set(self.folder.folder_id, user_id)
        self.redraw()
