import json
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form, Request
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.orm import Session
from sqlalchemy.exc import IntegrityError

from core.db import get_db, Poster, PosterLike
from core.crypt import decode_jwt, is_admin
from core.file import get_upload_dir, save_file, get_poster_dir, generate_file_url
from pydantic import BaseModel, EmailStr
from datetime import datetime

router = APIRouter()
security = HTTPBearer()

@router.get("/getallposter")
async def get_all_poster(
    db: Session = Depends(get_db),
):
    posters = db.query(Poster).all()
    if not posters:
        raise HTTPException(status_code=404, detail="Постеры не найдены.")
    
    return {
        "posters": [
            {
                "id": poster.id,
                "title": poster.title,
                "description": (poster.description[:250] + "...") if poster.description and len(poster.description) > 250 else poster.description,
                "image": poster.image,
                "date": poster.date.isoformat() if poster.date else None,
                "price": poster.price,
                "like": poster.like,
            }
            for poster in posters
        ]
    }

@router.post("/postercreate")
def create_poster(
    title: str = Form(...),
    description: str = Form(...),
    price: int = Form(...),
    date: datetime = Form(...),
    file: UploadFile = File(...),
    db: Session = Depends(get_db),
    credentials: HTTPAuthorizationCredentials = Depends(security),
    request: Request = None,
):
    
    token = credentials.credentials
    decoded_data = decode_jwt(token)
    user_id = decoded_data.get("user_id")

    if not is_admin(user_id, db):
        raise HTTPException(status_code=403, detail="Недостаточно прав для выполнения этого действия.")
    
    if not file:
        raise HTTPException(status_code=400, detail="Файл не был загружен.")
    
    if not file.filename.endswith(('.jpg', '.jpeg', '.png')):
        raise HTTPException(status_code=400, detail="Недопустимый формат файла. Допустимые форматы: .jpg, .jpeg, .png.")
    
    try:
        poster_id = db.query(Poster).count() + 1
        upload_dir = get_poster_dir(poster_id)
        file_path = save_file(file, upload_dir)
        file_url = generate_file_url(request, file_path)

        new_poster = Poster(
            title=title,
            description=description,
            date=date,
            price=price,
            like=0,
            datecreation=datetime.utcnow(),
            image=str(file_url),
        )
        db.add(new_poster)
        db.commit()
        db.refresh(new_poster)
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=f"Ошибка при загрузке файла: {str(e)}")

    return {"message": "Постер успешно создан.", "poster": new_poster}

@router.post("/posterupdate")
def update_poster(
    poster_id: int = Form(...),
    title: str = Form(...),
    description: str = Form(...),
    price: int = Form(...),
    date: datetime = Form(...),
    file: UploadFile = File(None),
    db: Session = Depends(get_db),
    credentials: HTTPAuthorizationCredentials = Depends(security),
    request: Request = None,
):
    
    token = credentials.credentials
    decoded_data = decode_jwt(token)
    user_id = decoded_data.get("user_id")

    if not is_admin(user_id, db):
        raise HTTPException(status_code=403, detail="Недостаточно прав для выполнения этого действия.")
    
    poster = db.query(Poster).filter(Poster.id == poster_id).first()
    
    if not poster:
        raise HTTPException(status_code=404, detail="Постер не найден.")
    
    if file:
        if not file.filename.endswith(('.jpg', '.jpeg', '.png')):
            raise HTTPException(status_code=400, detail="Недопустимый формат файла. Допустимые форматы: .jpg, .jpeg, .png.")
        
        try:
            upload_dir = get_poster_dir(poster_id)
            file_path = save_file(file, upload_dir)
            file_url = generate_file_url(request, file_path)
            poster.image = str(file_url)
        except Exception as e:
            db.rollback()
            raise HTTPException(status_code=500, detail=f"Ошибка при загрузке файла: {str(e)}")
    
    poster.title = title
    poster.description = description
    poster.date = date
    poster.price = price
    
    try:
        db.commit()
        db.refresh(poster)
    except IntegrityError:
        db.rollback()
        raise HTTPException(status_code=400, detail="Ошибка при обновлении постера.")
    
    return {"message": "Постер успешно обновлен.", "poster": poster}


@router.post("/setlike")
def set_like(
    poster_id: int = Form(...),
    like: int = Form(...),
    db: Session = Depends(get_db),
    credentials: HTTPAuthorizationCredentials = Depends(security),
):
    token = credentials.credentials
    decoded_data = decode_jwt(token)
    user_id = decoded_data.get("user_id")

    if not user_id:
        raise HTTPException(status_code=401, detail="Пользователь не авторизован.")
    
    # Проверка существования постера
    poster = db.query(Poster).filter(Poster.id == poster_id).first()
    if not poster:
        raise HTTPException(status_code=404, detail="Постер не найден.")
    
    # Валидация значения like
    if like not in [1, -1]:
        raise HTTPException(status_code=400, detail="Значение like должно быть 1 или -1.")
    
    try:
        # Проверка на существующий лайк
        existing_like = db.query(PosterLike).filter(
            PosterLike.poster_id == poster_id, 
            PosterLike.user_id == user_id
        ).first()
        
        if like == 1:
            # Пользователь хочет поставить лайк
            if existing_like:
                # Лайк уже есть - ничего не делаем
                return {
                    "message": "Вы уже оценили этот постер.",
                    "poster": {
                        "id": poster.id,
                        "title": poster.title,
                        "like": poster.like,
                        "image": poster.image,
                        "price": poster.price,
                        "date": poster.date.isoformat(),
                        "description": poster.description
                    }
                }
            else:
                # Добавляем лайк
                new_like = PosterLike(poster_id=poster_id, user_id=user_id)
                db.add(new_like)
                poster.like += 1
        else:
            # Пользователь хочет убрать лайк
            if existing_like:
                # Удаляем запись о лайке
                db.delete(existing_like)
                poster.like -= 1
            else:
                # Лайка не было - ничего не делаем
                return {
                    "message": "Вы еще не ставили лайк этому постеру.",
                    "poster": {
                        "id": poster.id,
                        "title": poster.title,
                        "like": poster.like,
                        "image": poster.image,
                        "price": poster.price,
                        "date": poster.date.isoformat(),
                        "description": poster.description
                    }
                }
        
        db.commit()
        db.refresh(poster)
        
        return {
            "message": "Лайк успешно обновлен.",
            "poster": {
                "id": poster.id,
                "title": poster.title,
                "like": poster.like,
                "image": poster.image,
                "price": poster.price,
                "date": poster.date.isoformat(),
                "description": poster.description
            }
        }
        
    except IntegrityError as e:
        db.rollback()
        print(f"Ошибка IntegrityError: {str(e)}")
        raise HTTPException(status_code=400, detail="Ошибка при обновлении лайка постера.")
    except Exception as e:
        db.rollback()
        print(f"Неожиданная ошибка: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Произошла ошибка: {str(e)}")
    

@router.get("/getposter/{poster_id}")
async def get_poster(
    poster_id: int,
    db: Session = Depends(get_db),
):
    poster = db.query(Poster).filter(Poster.id == poster_id).first()
    
    if not poster:
        raise HTTPException(status_code=404, detail="Постер не найден.")
    
    return {
        "id": poster.id,
        "title": poster.title,
        "description": poster.description,
        "image": poster.image,
        "date": poster.date.isoformat() if poster.date else None,
        "price": poster.price,
        "like": poster.like,
    }
