from fpdf import FPDF
import os
from datetime import datetime, timedelta
from asgiref.sync import sync_to_async
from django.utils.timezone import make_aware, is_aware, localtime
import pytz
from bot.utils.date_utils import ensure_datetime
from touchh.utils.log import CustomLogger

logger = CustomLogger(name="CustomPDF Report", log_level="DEBUG").get_logger()

# Определение абсолютного пути к папке "reports"
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
REPORTS_DIR = os.path.join(BASE_DIR, "reports")
os.makedirs(REPORTS_DIR, exist_ok=True)

@sync_to_async
def get_reservation_data(res):
    check_in = ensure_datetime(res.check_in)
    check_out = ensure_datetime(res.check_out)

    if not check_in or not check_out:
        raise ValueError(f"Некорректные даты бронирования: check_in={res.check_in}, check_out={res.check_out}")

    return {
        "hotel_name": res.hotel.name,
        "pms": getattr(res.hotel, 'pms', 'N/A'),
        "reservation_id": res.reservation_id,
        "room_number": res.room_number if res.room_number else "Не указан",
        "room_type": res.room_type,
        "check_in": check_in,
        "check_out": check_out,
        "status": res.status,
    }

def sanitize_text(text):
    return text.replace("\n", " ").strip() if isinstance(text, str) else text

class CustomPDF(FPDF):
    def __init__(self, hotel_name, start_date, end_date, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.font_folder = "bot/fonts/"
        self.add_font("DejaVuSans-Bold", "", os.path.join(self.font_folder, "DejaVuSans-Bold.ttf"), uni=True)
        self.add_font("DejaVuSans", "", os.path.join(self.font_folder, "DejaVuSans.ttf"), uni=True)
        self.creation_date = ensure_datetime(datetime.now(pytz.UTC))
        self.hotel_name = hotel_name
        self.start_date = start_date
        self.end_date = end_date

    def header(self):
        if self.page == 1:
            self.set_font("DejaVuSans-Bold", size=14)
            self.cell(0, 10, f"Отчет о бронированиях отеля {self.hotel_name}", ln=1, align="C")
            self.ln(5)
            self.set_font("DejaVuSans", size=10)
            self.cell(
                0, 
                10, 
                f"за период {self.start_date.strftime('%Y-%m-%d %H:%M:%S')} - {self.end_date.strftime('%Y-%m-%d %H:%M:%S')}", 
                ln=1, 
                align="C"
            )
            self.ln(10)

    def footer(self):
        self.set_y(-15)
        self.set_font("DejaVuSans", size=8)
        self.cell(60, 10, f"Copyright (C) 2024 by Touchh", align="L")
        self.cell(0, 10, f"Лист {self.page_no()} из {{nb}} / Дата генерации отчета: {self.creation_date}", align="C")

async def generate_pdf_report(hotel_name, reservations, start_date, end_date):
    start_date = ensure_datetime(start_date)
    end_date = ensure_datetime(end_date)

    logger.debug(f"Start_DATE: {start_date} / TYPE: {type(start_date)}")
    logger.debug(f"END_DATE: {end_date} / TYPE: {type(end_date)}")

    if not start_date or not end_date:
        raise ValueError("Некорректные даты для генерации отчета.")

    pdf = CustomPDF(hotel_name=hotel_name, start_date=start_date, end_date=end_date, orientation="L", unit="mm", format="A4")
    pdf.alias_nb_pages()
    pdf.add_page()

    pdf.set_font("DejaVuSans", size=8)
    col_widths = [30, 30, 30, 60, 35, 35, 30]
    row_height = 10

    for res in reservations:
        try:
            res_data = await get_reservation_data(res)
            res_data["check_in"] = ensure_datetime(res_data["check_in"])
            res_data["check_out"] = ensure_datetime(res_data["check_out"])

            row_data = [
                sanitize_text(res_data["hotel_name"]),
                sanitize_text(str(res_data["reservation_id"])),
                sanitize_text(str(res_data["room_number"])),
                sanitize_text(str(res_data["room_type"])),
                res_data["check_in"].strftime('%Y-%m-%d %H:%M:%S'),
                res_data["check_out"].strftime('%Y-%m-%d %H:%M:%S'),
                sanitize_text(res_data["status"]),
            ]

            for col_width, data in zip(col_widths, row_data):
                pdf.cell(col_width, row_height, data, border=1, align="C")
            pdf.ln()
        except Exception as e:
            logger.error(f"[ERROR] Error processing reservation {res.id}: {e}")

    pdf_output_path = os.path.join(REPORTS_DIR, f"{hotel_name.replace(' ', '_')}_report_{start_date.strftime('%Y-%m-%d')}-{end_date.strftime('%Y-%m-%d')}.pdf")
    logger.debug(f"PDF output path: {pdf_output_path}")

    pdf.output(pdf_output_path)

    if not os.path.exists(pdf_output_path):
        raise RuntimeError(f"PDF file was not created at: {pdf_output_path}")

    return pdf_output_path
