from datetime import datetime, timezone
from typing import Optional

from fastapi import APIRouter, Query, status

from repositories.service_repository import ServiceRepository
from repositories.user_repository import UserRepository
from schemas.service import ServiceSchema, CreateServiceRequest, UpdateServiceRequest
from utils.auth_dependency import handles_authentication, user_dependency
from utils.database import db_dependency
from utils.exceptions import NotFoundException
from utils.response import Response, ObjectResponseModel, ListResponseModel, BaseResponseModel
from utils.constants import BusinessType, RegisterStep

router = APIRouter(prefix="/api/services", tags=["Services"])


@router.post("/create", status_code=status.HTTP_201_CREATED, response_model=ObjectResponseModel)
@handles_authentication
async def create_service(user: user_dependency, request: CreateServiceRequest, db: db_dependency):
    service_repo = ServiceRepository(db)
    user_repo = UserRepository(db)

    user_data = await user_repo.get_by_id(user.get('id'))
    if not user_data.default_company:
        raise NotFoundException("default company")
    
    await user_repo.update_step(user.get('id'), RegisterStep.SETUP_SERVICES)

    service_data = ServiceSchema(
        company_id=user_data.default_company,
        name=request.name,
        price=request.price,
        created_at=datetime.now(timezone.utc),
        updated_at=datetime.now(timezone.utc)
    ) 

    service = await service_repo.create_service(service_data)

    return Response.post(name="Service", obj={'id': service.id, 'name': service.name, 'price': service.price})

@router.put("/{service_id}", status_code=status.HTTP_200_OK, response_model=ObjectResponseModel)
@handles_authentication
async def update_service(
    user: user_dependency,
    service_id: int,
    request: UpdateServiceRequest,
    db: db_dependency
):
    service_repo = ServiceRepository(db)
    user_repo = UserRepository(db)

    user_data = await user_repo.get_by_id(user.get('id'))
    if not user_data.default_company:
        raise NotFoundException("default company")

    service = await service_repo.get_by_id(service_id)
    if not service:
        raise NotFoundException("Service")

    if service.company_id != user_data.default_company:
        raise NotFoundException("Service")

    update_data = {
        'id': service.id,
        'company_id': service.company_id,
        'name': request.name if request.name is not None else service.name,
        'price': request.price if request.price is not None else service.price,
        'created_at': service.created_at,
        'updated_at': datetime.now(timezone.utc)
    }
    
    service_schema = ServiceSchema(**update_data)
    updated_service = await service_repo.update(service_id, service_schema)

    return Response.put(
        name="Service",
        obj={'id': updated_service.id, 'name': updated_service.name, 'price': updated_service.price}
    )

@router.get("/read-all", status_code=status.HTTP_200_OK, response_model=ListResponseModel)
@handles_authentication
async def get_services(
    user: user_dependency,
    db: db_dependency,
    start: int = Query(0, ge=0),
    page_size: int = Query(10, ge=1, le=100),
    search: Optional[str] = None
):
    service_repo = ServiceRepository(db)
    user_repo = UserRepository(db)

    user_data = await user_repo.get_by_id(user.get('id'))
    if not user_data.default_company:
        raise NotFoundException("default company")

    total = await service_repo.count_by_company(user_data.default_company, search)
    
    services = await service_repo.get_by_company_paginated(
        company_id=user_data.default_company,
        start=start,
        size=page_size,
        search=search
    )

    return Response.list(
        entities=services,
        total_count=total,
        page_size=page_size,
        name="Services"
    )

@router.delete("/{service_id}", status_code=status.HTTP_200_OK, response_model=BaseResponseModel)
@handles_authentication
async def delete_service(
    user: user_dependency,
    service_id: int,
    db: db_dependency
):
    service_repo = ServiceRepository(db)
    user_repo = UserRepository(db)

    user_data = await user_repo.get_by_id(user.get('id'))
    if not user_data.default_company:
        raise NotFoundException("default company")

    service = await service_repo.get_by_id(service_id)
    if not service:
        raise NotFoundException("Service")

    if service.company_id != user_data.default_company:
        raise NotFoundException("Service")

    deleted_service = await service_repo.delete_service(service_id)
    if not deleted_service:
        raise NotFoundException("Service")

    return Response.delete(name="Service")
