import flet as ft
import requests
from helpers.roles import Roles
from dataclasses import dataclass, field
from datetime import datetime

@dataclass
class State:
    
    file_picker: ft.FilePicker | None = None
    picked_files: list[ft.FilePickerFile] = field(default_factory=list)


state = State()

class DocumenteJuridice:
    def __init__(self, page: ft.Page):
        self.page = page
        self.editing_category_id = None
        self.category_id_to_delete = None
        self.document_id_to_delete = None
        self.current_category_id = None

        self.search_bar = ft.TextField(
            label="Cauta", 
            on_submit=self.on_search_bar_submit, 
            expand=True
        )
        self.category_name = ft.TextField(
            label="Nume categorie",
        )

        self.roles_checkboxes = [
            ft.Checkbox(label=role.upper())
            for role in [
                Roles.USER, Roles.PROPRIETAR, Roles.CENZOR,
                Roles.ADMINISTRATOR, Roles.PRESEDINTE, Roles.EXPERT
            ]
        ]

        self.access_levels = ft.Column(
            controls=self.roles_checkboxes,
            height=200,
            scroll=ft.ScrollMode.AUTO
        )

        self.add_categories_dialog = ft.AlertDialog(
            title=ft.Text("Adauga Categorie"),
            content=ft.Column(
                [
                    self.category_name,
                    ft.Text("Nivele Acces:"),
                    self.access_levels
                ],
                height=300,
                tight=True
            ),
            actions=[
                ft.FilledButton(
                    "Salveaza", 
                    on_click=self.on_save_category_btn_click
                ),
                ft.FilledButton(
                    "Anuleaza", 
                    on_click=self.on_cancel_category_btn_click,
                    bgcolor=ft.Colors.GREY,
                ),
            ],
        )

        self.delete_confirmation_dialog = ft.AlertDialog(
            title=ft.Text("Doriti sa stergeti categoria?"),
            content=ft.Text("Stergerea categoriei implica si stergerea tuturor documentelor din aceasta categorie."),
            actions=[
                ft.FilledButton(
                    "Da", 
                    on_click=self.confirm_delete_category
                ),
                ft.FilledButton(
                    "Nu", 
                    bgcolor=ft.Colors.GREY, 
                    on_click=self.close_delete_dialog
                ),
            ],
        )

        self.delete_document_confirmation_dialog = ft.AlertDialog(
            title=ft.Text("Doriti sa stergeti documentul?"),
            content=ft.Text("Aceasta actiune este permanenta."),
            actions=[
                ft.FilledButton(
                    "Da", 
                    on_click=self.confirm_delete_document
                ),
                ft.FilledButton(
                    "Nu", 
                    bgcolor=ft.Colors.GREY, 
                    on_click=self.close_delete_document_dialog
                ),
            ],
        )

        self.all_categories = self.get_categories()
        self.category_list = ft.ListView(
            controls=self.create_category_list(
                self.all_categories, 
                self.on_edit_category_btn_click,
                self.on_delete_category_btn_click
            ),
            spacing=10,
            expand=True
        )

        self.add_document = ft.Button(
            "Adauga Document", 
            icon=ft.Icons.ADD,
            on_click=self.add_new_document
        )

        self.all_documents = []
        self.documents_list = ft.ListView(
            spacing=10,
            expand=True
        )

        self.category = ft.Dropdown(
            label="Selectează Categoria",
            options=[
                ft.dropdown.Option(key=str(cat['id']), text=cat['name']) 
                for cat in self.all_categories
            ]
        )

        self.documenet_title = None
        self.documenet_displayed_title = ft.TextField(label="Document",read_only=True)
        self.add_new_document_dialog = ft.AlertDialog(
            title=ft.Text("Adauga document"),
            content=ft.Column(
                [
                    ft.Row(
                        [
                            self.documenet_displayed_title,
                            ft.Button(
                                "Incarca", 
                                icon=ft.Icons.UPLOAD, 
                                on_click=self.handle_file_upload
                            ),
                        ]
                    ),
                    self.category
                ],
                height=160,
            ),
            actions=[
                ft.FilledButton(
                    "Salveaza", 
                    on_click=self.on_save_document_btn_click,

                ),
                ft.FilledButton(
                    "Anuleaza", 
                    bgcolor=ft.Colors.GREY, 
                    on_click=self.on_cancel_save_dialog_btn_click,
                ),
            ],
        )

    def on_add_btn_click(self, e):
        self.editing_category_id = None
        self.category_name.value = ""
        for cb in self.roles_checkboxes:
            cb.value = False
        self.add_categories_dialog.title = ft.Text("Adauga Categorie")
        self.page.show_dialog(self.add_categories_dialog)
        self.page.update()
    
    def on_save_category_btn_click(self, e):
        category = self.category_name.value
        access = ",".join([cb.label for cb in self.roles_checkboxes if cb.value])
        base_url = self.page.session.store.get('api_base_url')
        token = self.page.session.store.get('token')

        if self.editing_category_id:
            url = f'{base_url}/documents/categories/update/{self.editing_category_id}'
            method = requests.put
        else:
            url = f'{base_url}/documents/categories/add'
            method = requests.post

        response = method( 
            url,
            json={
                "name": category,
                "access": access 
            }, 
            headers = {
                    'Authorization': f'Bearer {token}',
                    'Content-Type': 'application/json'
                }
            )
        
        if response.status_code in [200, 201]:
            self.update_category_list()
            self.category_name.value = None
            self.editing_category_id = None
            self.page.pop_dialog()
        else:
            raise Exception("Operatiuna nu sa putut realiza, token-ul a expirat, va rugam sa va autentificati. Daca eroarea persita contactati echipa de IT!")
            

    def update_category_list(self):
        self.all_categories = self.get_categories()
        self.category_list.controls = self.create_category_list(
            self.all_categories, 
            self.on_edit_category_btn_click,
            self.on_delete_category_btn_click
        )
        self.category_list.update()

        # Actualizăm și opțiunile din dropdown-ul pentru documente
        self.category.options = [
            ft.dropdown.Option(key=str(cat['id']), text=cat['name'])
            for cat in self.all_categories
        ]

    def on_cancel_category_btn_click(self, e):
        self.category_name.value = None
        self.page.pop_dialog()

    def on_search_bar_submit(self, e):
        # Luăm textul din search bar și îl convertim la litere mici pentru o căutare case-insensitive
        query = self.search_bar.value.strip().lower()
        
        # Filtrăm lista de documente stocată în self.all_documents
        if not query:
            filtered_docs = self.all_documents
        else:
            filtered_docs = [
                doc for doc in self.all_documents 
                if query in doc['name'].lower()
            ]
        
        # Actualizăm interfața cu lista filtrată
        self.documents_list.controls = self.create_documents_list(
            filtered_docs,
            lambda doc: self.page.run_task(self.on_download_document_btn_click, doc),
            self.on_delete_document_btn_click
        )
        self.documents_list.update()

    def add_new_document(self, e):
        self.page.show_dialog(self.add_new_document_dialog)

    async def handle_file_upload(self, e: ft.Event[ft.Button]):
        print('File uploaded')
        try:
            state.file_picker = ft.FilePicker()
            files = await state.file_picker.pick_files(allow_multiple=False)
            print("Picked file:", files)
            
            state.picked_files = files
            uploaded_file_name = f"{datetime.now().strftime('%Y%m%d%H%M%S')}_{state.picked_files[0].name}"
            await state.file_picker.upload(    
            files=[          
                    ft.FilePickerUploadFile(                
                        name=file.name,                 
                        upload_url=self.page.get_upload_url(uploaded_file_name, 60),
                                    
                    )
                                    
                    for file in state.picked_files     
                ]
            )
            self.documenet_title = uploaded_file_name
            self.documenet_displayed_title.value = uploaded_file_name.split("_")[1]
            self.documenet_displayed_title.update()
            return f'{uploaded_file_name}'
        except Exception as e:
            print(e)
    
    def on_save_document_btn_click(self, e):
        if not self.category.value or not self.documenet_title:
            # Opțional: Poți adăuga un mesaj de eroare vizibil pentru utilizator
            return

        selected_cat_id = int(self.category.value)
        # Identificăm obiectul categoriei pentru a-i moșteni accesul și numele
        category = next((cat for cat in self.all_categories if cat['id'] == selected_cat_id), None)
        
        if not category:
            return

        base_url = self.page.session.store.get('api_base_url')
        token = self.page.session.store.get('token')

        # Construim path-ul relativ (Categorie/NumeFisier)
        dest_path = f"{category['name']}/{self.documenet_title}"

        payload = {
            "category_id": selected_cat_id,
            "name": self.documenet_displayed_title.value,
            "path": dest_path,
            "access": category.get('access', '') # Moștenim accesul de la categorie
        }

        response = requests.post(
            f"{base_url}/documents/standards/add",
            json=payload,
            headers={'Authorization': f'Bearer {token}'}
        )

        if response.status_code == 201:
            self.page.pop_dialog()
            self.list_all_category_documents(selected_cat_id)
            # Resetăm câmpurile după salvarea cu succes
            self.documenet_title = None
            self.documenet_displayed_title.value = ""

    def on_cancel_save_dialog_btn_click(self, e):
        self.documenet_title = None
        self.documenet_displayed_title.value = ""
        self.page.pop_dialog()

    def create_category_list(self, items, on_click_handler, on_click_handler2):
        """Helper to create list items for a column."""
        return [
            ft.Container(
                content=ft.Row(
                    [

                        ft.Row(
                            [
                                ft.Icon(ft.Icons.ARROW_RIGHT, size=20),
                                ft.Text(value=item['name'])
                            ]
                        ),
             
                        ft.Row(
                            [
                                ft.IconButton(
                                    icon=ft.Icons.EDIT,
                                    on_click=lambda e, id=item: on_click_handler(id),
                                ),
                                ft.IconButton(
                                    icon=ft.Icons.REFRESH,
                                    on_click=lambda e, id=item['id']: self.on_refresh_category_click(id),
                                    icon_color=ft.Colors.BLUE_400,
                                ),
                                ft.IconButton(
                                    icon=ft.Icons.DELETE,
                                    on_click=lambda e, id=item['id']: on_click_handler2(id), 
                                    icon_color=ft.Colors.RED,
                                ),
                            ]
                        )
                        
                    ],
                    alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
                ),
                expand=True,
                bgcolor=ft.Colors.BLUE_50,
                border = ft.Border.all(1, ft.Colors.GREY),
                padding=10,
                border_radius=8,
                ink=True,
                on_click=lambda e, cid=item['id']: self.list_all_category_documents(cid)
            )
            for item in items
        ]
    
    def on_edit_category_btn_click(self, category):
        self.editing_category_id = category['id']
        self.category_name.value = category['name']
        
        access_list = category.get('access', '').split(',')
        for cb in self.roles_checkboxes:
            cb.value = cb.label in access_list
            
        self.add_categories_dialog.title = ft.Text("Editeaza Categorie")
        self.page.show_dialog(self.add_categories_dialog)
        self.page.update()

    def on_refresh_category_click(self, category_id):
        base_url = self.page.session.store.get('api_base_url')
        token = self.page.session.store.get('token')
        
        try:
            response = requests.post(
                f'{base_url}/documents/categories/refresh/{category_id}',
                headers={'Authorization': f'Bearer {token}'}
            )
            
            if response.status_code == 200:
                added = response.json().get("added", 0)
                # Daca suntem in categoria care s-a improspatat, reincarcam lista de documente
                if self.current_category_id == category_id:
                    self.list_all_category_documents(category_id)
                
                # Notificare succes
                self.page.snack_bar = ft.SnackBar(
                    content=ft.Text(f"Refresh complet. S-au adaugat {added} documente."),
                    bgcolor=ft.Colors.GREEN_400
                )
                self.page.snack_bar.open = True
                self.page.update()
        except Exception as e:
            print(f"Error during category refresh: {e}")

    def on_delete_category_btn_click(self, category_id):
        self.category_id_to_delete = category_id
        self.page.show_dialog(self.delete_confirmation_dialog)
        self.page.update()

    def confirm_delete_category(self, e):
        if self.category_id_to_delete:
            base_url = self.page.session.store.get('api_base_url')
            token = self.page.session.store.get('token')
            
            response = requests.delete(
                f'{base_url}/documents/categories/delete/{self.category_id_to_delete}',
                headers={'Authorization': f'Bearer {token}'}
            )
            
            if response.status_code == 200:
                # Dacă categoria ștearsă este cea ale cărei documente sunt afișate, golim lista
                if self.current_category_id == self.category_id_to_delete:
                    self.documents_list.controls = []
                    self.documents_list.update()
                    self.current_category_id = None

                self.update_category_list()
        
        self.category_id_to_delete = None
        self.page.pop_dialog()

    def close_delete_dialog(self, e):
        self.category_id_to_delete = None
        self.page.pop_dialog()

    def get_categories(self):
        base_url = self.page.session.store.get('api_base_url')
        token = self.page.session.store.get('token')
        try:
            response = requests.get(
                f'{base_url}/documents/categories',
                headers={'Authorization': f'Bearer {token}'}
            )
            if response.status_code == 200:
                return response.json()
        except Exception as e:
            print(f"Error fetching categories: {e}")
        return []
    
    def list_all_category_documents(self, category_id):
        self.current_category_id = category_id
        self.all_documents = self.get_all_documents(category_id) or []
        self.documents_list.controls = self.create_documents_list(
            self.all_documents,
            lambda doc: self.page.run_task(self.on_download_document_btn_click, doc),
            self.on_delete_document_btn_click
        )
        self.documents_list.update()

    async def on_download_document_btn_click(self, document):
        base_url = self.page.session.store.get('api_base_url')
        token = self.page.session.store.get('token')
        # Deschidem link-ul de download în browser
        # path în document este de forma "NumeCategorie/fisier.ext"
        download_url = f"{base_url}/documents/download?path={document['path']}&token={token}"
        await self.page.launch_url(download_url)

    def on_delete_document_btn_click(self, doc_id):
        self.document_id_to_delete = doc_id
        self.page.show_dialog(self.delete_document_confirmation_dialog)
        self.page.update()

    def confirm_delete_document(self, e):
        if self.document_id_to_delete:
            base_url = self.page.session.store.get('api_base_url')
            token = self.page.session.store.get('token')
            
            response = requests.delete(
                f'{base_url}/documents/standards/delete/{self.document_id_to_delete}',
                headers={'Authorization': f'Bearer {token}'}
            )
            
            if response.status_code == 200:
                if hasattr(self, 'current_category_id'):
                    self.list_all_category_documents(self.current_category_id)
        
        self.document_id_to_delete = None
        self.page.pop_dialog()

    def close_delete_document_dialog(self, e):
        self.document_id_to_delete = None
        self.page.pop_dialog()

    def get_all_documents(self, category_id):
        base_url = self.page.session.store.get('api_base_url')
        token = self.page.session.store.get('token')
        try:
            response = requests.get(
                f'{base_url}/documents/standards/category/{category_id}',
                headers={'Authorization': f'Bearer {token}'}
            )
            if response.status_code == 200:
                return response.json()
        except Exception as e:
            print(f"Error fetching documents: {e}")
        return []

    def create_documents_list(self, items, on_click_handler, on_click_handler2):
        """Helper to create list items for a column."""
        return [
            ft.Container(
                content=ft.Row(
                    [

                        ft.Row(
                            [
                                ft.Icon(ft.Icons.ARROW_RIGHT, size=20),
                                ft.Text(value=item['name'])
                            ]
                        ),
             
                        ft.Row(
                            [
                                ft.IconButton(
                                    icon=ft.Icons.DOWNLOAD,
                                    on_click=lambda e, id=item: on_click_handler(id),
                                ),
                                ft.IconButton(
                                    icon=ft.Icons.DELETE,
                                    on_click=lambda e, id=item['id']: on_click_handler2(id), 
                                    icon_color=ft.Colors.RED,
                                ),
                            ]
                        )
                        
                    ],
                    alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
                ),
                expand=True,
                bgcolor=ft.Colors.BLUE_50,
                border = ft.Border.all(1, ft.Colors.GREY),
                padding=10,
                border_radius=8
            )
            for item in items
        ]

    def build(self):
        return ft.Container(
            content=ft.Row(
                [
                    ft.Column(
                        [
                            ft.Row(
                                [
                                    ft.Button(
                                        "Adauga Categori", 
                                        icon=ft.Icons.ADD, 
                                        on_click=self.on_add_btn_click,
                                        width=300
                                    ),
                                ],
                                alignment=ft.MainAxisAlignment.CENTER
                            ),
                            self.category_list
                        ],
                        alignment=ft.MainAxisAlignment.START,
                        width = 350,
                    ),
                    ft.VerticalDivider(width=1),
                    ft.Column(
                        [
                            ft.Row(
                                [
                                    self.add_document
                                ],
                                alignment=ft.MainAxisAlignment.END
                            ),
                            ft.Row(
                                [
                                    self.search_bar
                                ]
                            ),
                            self.documents_list
                        ],
                        expand=True
                    )
                ],
            ),
            expand=True
        )