from http import HTTPStatus
from fastapi import Query, Request,Depends, APIRouter, UploadFile,HTTPException,File
from fastapi.responses import JSONResponse
# from app.core.operation import log_operation
# from app.db import Base,engine
from app.core.dbmanager import get_db
from app.db.crud import *
from app.db.schemas import *
from typing import List, Optional
from app.core.auth import get_current_active_user,get_current_user
from app.core.apiexception import APIException
from app.core.common import ApiReturnModel,ApiReturnPage
#from fastapi_pagination import Page 
from app.db.cruddb import domainService,appService

import httpx
import app.core.config as config
from app.core import domainCacheService,tenantCacheService

platform_router = r = APIRouter()

@r.get(
    "/test",
    response_model_exclude_none=True,
)
async def test(
    request: Request,
    user = Depends(get_current_active_user),
    db=Depends(get_db),
):
    domainService.select(db,{"tenantid":1,"name":["b","c"]})


@r.get(
    "/apps",tags=["App"],
    response_model=ApiReturnModel[List[AppList]|None],
    response_model_exclude_none=True,
)
async def apps_list(
    request: Request,
    user = Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
     
        domain = domainService.get_default_domain(db,user.id) #get_activedomain(db, user.id)
        if not domain:
            return  ApiReturnModel(data = None)
        filtered_apps = []
        platformapps = appService.get_apps(db,domain.url)
        kintoneevn = config.KINTONE_ENV(domain)
        headers={config.API_V1_AUTH_KEY:kintoneevn.API_V1_AUTH_VALUE}
        url = f"{kintoneevn.BASE_URL}{config.API_V1_STR}/apps.json"
        offset = 0
        limit = 100
        all_apps = [] 

        while True:
            r = httpx.get(f"{url}?limit={limit}&offset={offset}", headers=headers)
            json_data = r.json()
            apps = json_data.get("apps",[])
            all_apps.extend(apps)
            if len(apps)<limit:
                break
            offset += limit
        
        kintone_apps_dict = {app['appId']: app for app in all_apps}
        for papp in platformapps:
            if papp.appid in kintone_apps_dict:
                papp.appname = kintone_apps_dict[papp.appid]["name"]
                filtered_apps.append(papp)
        return ApiReturnModel(data = filtered_apps)
    except Exception as e:
        raise APIException('platform:apps',request.url._url,f"Error occurred while get apps:",e)

@r.post("/apps", tags=["App"],
        response_model=ApiReturnModel[AppList|None], 
        response_model_exclude_none=True)
async def apps_update(
    request: Request,
    app: VersionUpdate,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        domainurl = domainCacheService.get_default_domainurl(db,user.id)
        if not domainurl:
            return ApiReturnModel(data = None)
        return ApiReturnModel(data =appService.update_appversion(db, domainurl,app,user.id))
    except Exception as e:
        raise APIException('platform:apps',request.url._url,f"Error occurred while get create app :",e)
    
@r.delete("/apps/{appid}",tags=["App"],
    response_model=ApiReturnModel[AppList|None],
    response_model_exclude_none=True
)
async def apps_delete(
    request: Request,
    appid: str,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        domainurl = domainCacheService.get_default_domainurl(db,user.id) #get_activedomain(db, user.id)
        if not domainurl:
            return ApiReturnModel(data = None)
        return ApiReturnModel(data =appService.delete_app(db, domainurl,appid))
    except Exception as e:
        raise APIException('platform:apps',request.url._url,f"Error occurred while delete app({appid}):",e)

@r.get(
    "/appversions/{appid}",tags=["App"],
    response_model=ApiReturnPage[AppVersion|None],
    response_model_exclude_none=True,
)
async def appversions_list(
    request: Request,
    appid: str,
    user = Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        domainurl = domainCacheService.get_default_domainurl(db,user.id) #get_activedomain(db, user.id)
        if not domainurl:
            return ApiReturnPage(data = None)
        return appService.get_appversions(db,domainurl,appid)
    except Exception as e:
        raise APIException('platform:appversions',request.url._url,f"Error occurred while get app({appid}) version :",e)

@r.put(
    "/appversions/{appid}/{version}",tags=["App"],
      response_model=ApiReturnModel[AppList|None], 
      response_model_exclude_none=True
)
async def appversions_change(
    request: Request,
    appid: str,
    version: int,
    user = Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        domainurl = domainCacheService.get_default_domainurl(db,user.id) #get_activedomain(db, user.id)
        if not domainurl:
            ApiReturnModel(data = None)
        return ApiReturnModel(data = appService.change_appversion(db, domainurl,appid,version,user.id))
    except Exception as e:
        raise APIException('platform:appversions',request.url._url,f"Error occurred while change app version:",e)
       
@r.get(
    "/appsettings/{id}",
    response_model=App,
    response_model_exclude_none=True,
)
async def appsetting_details(
    request: Request,
    id: int,
    db=Depends(get_db),
):
    try:
        app = get_appsetting(db, id)
        return app
    except Exception as e:
        raise APIException('platform:appsettings',request.url._url,f"Error occurred while get app setting:",e)

@r.post("/appsettings", response_model=App, response_model_exclude_none=True)
async def appsetting_create(
    request: Request,
    app: AppBase,
    db=Depends(get_db),
):
    try:
        return create_appsetting(db, app)
    except Exception as e:
        raise APIException('platform:appsettings',request.url._url,f"Error occurred while get create app setting:",e)


@r.put(
    "/appsettings/{id}", response_model=App, response_model_exclude_none=True
)
async def appsetting_edit(
    request: Request,
    id: int,
    app: AppEdit,
    db=Depends(get_db),
):
    try:
        return edit_appsetting(db, id, app)
    except Exception as e:
        raise APIException('platform:appsettings',request.url._url,f"Error occurred while edit app setting:",e)


@r.delete(
    "/appsettings/{id}", response_model=App, response_model_exclude_none=True
)
async def appsettings_delete(
    request: Request,
    id: int,
    db=Depends(get_db),
):
    try:
        return delete_appsetting(db, id)
    except Exception as e:
        raise APIException('platform:appsettings',request.url._url,f"Error occurred while delete app setting:",e)


@r.get(
    "/kintone/{type}",
    response_model=t.List[Kintone],
    response_model_exclude_none=True,
)
async def kintone_data(
    request: Request,
    type: int,
    db=Depends(get_db),
):
    try:
        kintone = get_kintones(db, type)
        return kintone
    except Exception as e:
        raise APIException('platform:kintone',request.url._url,f"Error occurred while get kintone env:",e)

@r.get(
    "/actions",
    response_model=t.List[Action],
    response_model_exclude={"id"},
    response_model_exclude_none=True,
)
async def action_data(
    request: Request,
    db=Depends(get_db),
):
    try:
        actions = get_actions(db)
        return actions
    except Exception as e:
        raise APIException('platform:actions',request.url._url,f"Error occurred while get actions:",e)

@r.get(
    "/flow/{appid}",tags=["App"],
    response_model=ApiReturnModel[List[Flow]|None],
    response_model_exclude_none=True,
)
async def flow_details(
    request: Request,
    appid: str,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        domainurl = domainCacheService.get_default_domainurl(db,user.id) 
        if not domainurl:
            return ApiReturnModel(data = None)
        return ApiReturnModel(data = appService.get_flow(db, domainurl, appid))
    except Exception as e:
        raise APIException('platform:flow',request.url._url,f"Error occurred while get flow by flowid:",e)

@r.get(
    "/flows/{appid}", tags=["App"],
    response_model=List[Flow|None],
    response_model_exclude_none=True,
)
async def flow_list(
    request: Request,
    appid: str,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        domainurl = domainCacheService.get_default_domainurl(db,user.id) #get_activedomain(db, user.id)
        if not domainurl:
            return []
        #flows = get_flows_by_app(db, domainurl, appid)
        flows = appService.get_flow(db,domainurl,appid)
        return flows
    except Exception as e:
        raise APIException('platform:flow',request.url._url,f"Error occurred while get flow by appid:",e)
    

@r.post("/flow", tags=["App"],
        response_model=ApiReturnModel[Flow|None], 
        response_model_exclude_none=True)
async def flow_create(
    request: Request,
    flow: FlowIn,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        domainurl = domainCacheService.get_default_domainurl(db,user.id) #get_activedomain(db, user.id)
        if not domainurl:
            return ApiReturnModel(data = None)
        return ApiReturnModel(data = appService.create_flow(db, domainurl, flow,user.id))
    except Exception as e:
        raise APIException('platform:flow',request.url._url,f"Error occurred while create flow:",e)


@r.put(
    "/flow", tags=["App"], 
    response_model=ApiReturnModel[Flow|None], 
    response_model_exclude_none=True
)
async def flow_edit(
    request: Request,
    flow: FlowIn,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        domainurl = domainCacheService.get_default_domainurl(db,user.id) 
        if not domainurl:
            return ApiReturnModel(data = None)
        return ApiReturnModel(data = appService.edit_flow(db,domainurl, flow,user.id))
    except Exception as e:
        raise APIException('platform:flow',request.url._url,f"Error occurred while edit flow:",e)


@r.delete(
    "/flow/{flowid}", tags=["App"], 
    response_model=ApiReturnModel[Flow|None], 
    response_model_exclude_none=True
)
async def flow_delete(
    request: Request,
    flowid: str,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        domainurl = domainCacheService.get_default_domainurl(db,user.id) 
        if not domainurl:
            return ApiReturnModel(data = None)
        return ApiReturnModel(data = appService.delete_flow(db, flowid))
    except Exception as e:
        raise APIException('platform:flow',request.url._url,f"Error occurred while delete flow:",e)

@r.get(
    "/domains",tags=["Domain"],
    response_model=ApiReturnPage[Domain],
    response_model_exclude_none=True,
)
async def domain_list(
    request: Request,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        if user.is_superuser:
            domains = domainService.get_domains(db)
        else:
            domains = domainService.get_domains_by_manage(db,user.id)
        return  domains
    except Exception as e:
        raise APIException('platform:domains',request.url._url,f"Error occurred while get domains:",e)

@r.get(
    "/domain/{domain_id}",tags=["Domain"],
    response_model=ApiReturnModel[Domain|None],
    response_model_exclude_none=True,
)
async def domain_detail(
    request: Request,
    domain_id:int,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        return ApiReturnModel(data = domainService.get(db,domain_id))
    except Exception as e:
        raise APIException('platform:domain',request.url._url,f"Error occurred while get domain detail:",e)
    
@r.post("/domain", tags=["Domain"],
        response_model=ApiReturnModel[Domain], 
        response_model_exclude_none=True)
async def domain_create(
    request: Request,
    domain: DomainIn,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        return ApiReturnModel(data = domainService.create_domain(db, domain,user.id))
    except Exception as e:
        raise APIException('platform:domain',request.url._url,f"Error occurred while create domain:",e)


@r.put(
    "/domain", tags=["Domain"],
    response_model=ApiReturnModel[Domain|None], 
    response_model_exclude_none=True
)
async def domain_edit(
    request: Request,
    domain: DomainIn,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        domain = domainService.edit_domain(db, domain,user.id)
        if domain :
            domainCacheService.clear_default_domainurl()
        return ApiReturnModel(data = domain)
    except Exception as e:
        raise APIException('platform:domain',request.url._url,f"Error occurred while edit domain:",e)


@r.delete(
    "/domain/{id}",tags=["Domain"],
    response_model=ApiReturnModel[DomainOut|None], 
    response_model_exclude_none=True,
)
async def domain_delete(
    request: Request,
    id: int,
    db=Depends(get_db),
):
    try:
        return ApiReturnModel(data = domainService.delete_domain(db,id))
    except Exception as e:
        raise APIException('platform:domain',request.url._url,f"Error occurred while delete domain({id}):",e)

@r.get(
    "/domain",
    response_model=List[Domain],
    response_model_exclude_none=True,
)
async def userdomain_details(
    request: Request,
    userId: Optional[int] = Query(None, alias="userId"),
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        domains = get_domain(db, userId if userId is not None else user.id)
        return domains
    except Exception as e:
        raise APIException('platform:userdomain',request.url._url,f"Error occurred while get user({user.id}) domain:",e)

@r.post(
    "/userdomain",tags=["Domain"],
    response_model=ApiReturnModel[DomainOut|None],
    response_model_exclude_none=True,
)
async def create_userdomain(
    request: Request,
    userdomain:UserDomainParam,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        userid = userdomain.userid
        domainid = userdomain.domainid
        if user.is_superuser:
            domain = domainService.add_userdomain(db,user.id,userid,domainid)
        else:
            domain = domainService.add_userdomain_by_owner(db,user.id,userid,domainid)
        return ApiReturnModel(data = domain)
    except Exception as e:
        raise APIException('platform:userdomain',request.url._url,f"Error occurred while add user({userid}) domain({domainid}):",e)

@r.delete(
    "/domain/{domainid}/{userid}",tags=["Domain"],
    response_model=ApiReturnModel[DomainOut|None],
    response_model_exclude_none=True,
)
async def delete_userdomain(
    request: Request,
    domainid:int,
    userid: int,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        return ApiReturnModel(data = domainService.delete_userdomain(db,userid,domainid))
    except Exception as e:
        raise APIException('platform:userdomain',request.url._url,f"Error occurred while delete user({userid}) domain({domainid}):",e)



@r.get(
    "/managedomainuser/{domainid}",tags=["Domain"],
    response_model=ApiReturnPage[UserOut|None],
    response_model_exclude_none=True,
)
async def get_managedomainuser(
    request: Request,
    domainid:int,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        return domainService.get_managedomain_users(db,domainid)
    except Exception as e:
        raise APIException('platform:managedomain',request.url._url,f"Error occurred while get managedomain({user.id}) user:",e)




@r.post(
    "/managedomain",tags=["Domain"],
    response_model=ApiReturnModel[DomainOut|None],
    response_model_exclude_none=True,
)
async def create_managedomain(
    request: Request,
    userdomain:UserDomainParam,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        userid = userdomain.userid
        domainid = userdomain.domainid
        if user.is_superuser:
            domain = domainService.add_managedomain(db,user.id,userid,domainid)
        else:
            domain = domainService.add_managedomain_by_owner(db,user.id,userid,domainid)
        return ApiReturnModel(data = domain)
    except Exception as e:
        raise APIException('platform:managedomain',request.url._url,f"Error occurred while add manage({userid}) domain({domainid}):",e)

@r.delete(
    "/managedomain/{domainid}/{userid}",tags=["Domain"],
    response_model=ApiReturnModel[DomainOut|None],
    response_model_exclude_none=True,
)
async def delete_managedomain(
    request: Request,
    domainid:int,
    userid: int,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        return ApiReturnModel(data = domainService.delete_managedomain(db,userid,domainid))
    except Exception as e:
        raise APIException('platform:managedomain',request.url._url,f"Error occurred while delete managedomain({userid}) domain({domainid}):",e)
    
@r.get(
    "/defaultdomain",tags=["Domain"],
    response_model=ApiReturnModel[DomainOut|None],
    response_model_exclude_none=True,
)
async def get_defaultuserdomain(
    request: Request,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        return ApiReturnModel(data =domainService.get_default_domain(db,user.id))
    except Exception as e:
        raise APIException('platform:defaultdomain',request.url._url,f"Error occurred while get user({user.id}) defaultdomain:",e)
    
@r.put(
    "/defaultdomain/{domainid}",tags=["Domain"],
    response_model=ApiReturnModel[DomainOut|None],
    response_model_exclude_none=True,
)
async def set_defualtuserdomain(
    request: Request,
    domainid:int,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        domain = domainCacheService.set_default_domain(db,user.id,domainid)
        return ApiReturnModel(data= domain)
    except Exception as e:
        raise APIException('platform:defaultdomain',request.url._url,f"Error occurred while update user({user.id}) defaultdomain:",e)


@r.get(
    "/domainshareduser/{domainid}",tags=["Domain"],
    response_model=ApiReturnPage[UserOut|None],
    response_model_exclude_none=True,
)
async def get_domainshareduser(
    request: Request,
    domainid:int,
    user=Depends(get_current_active_user),
    db=Depends(get_db),
):
    try:
        return domainService.get_shareddomain_users(db,domainid)
    except Exception as e:
        raise APIException('platform:sharedomain',request.url._url,f"Error occurred while get user({user.id}) sharedomain:",e)


@r.get(
    "/events",
    response_model=t.List[Event],
    response_model_exclude={"id"},
    response_model_exclude_none=True,
)
async def event_data(
    request: Request,
    db=Depends(get_db),
):
    try:
        events = get_events(db)
        return events
    except Exception as e:
        raise APIException('platform:events',request.url._url,f"Error occurred while get events:",e)


@r.get(
    "/eventactions/{eventid}",
    response_model=t.List[Action],
    response_model_exclude={"id"},
    response_model_exclude_none=True,
)
async def eventactions_data(
    request: Request,
    eventid: str,
    db=Depends(get_db),
):
    try:
        actions = get_eventactions(db,eventid)
        return actions
    except Exception as e:
        raise APIException('platform:eventactions',request.url._url,f"Error occurred while get eventactions:",e)