from fastapi import Request,Depends, APIRouter, UploadFile,HTTPException,File
from io import BytesIO
import typing as t
import pandas as pd
import json
import base64
import httpx
import deepdiff
import app.core.config as config
import os
from pathlib import Path
from app.core.dbmanager import get_db
from app.db.crud import get_flows_by_app,get_kintoneformat
from app.core.auth import get_current_active_user,get_current_user
from app.core.apiexception import APIException
from app.db.cruddb import domainService,appService

kinton_router = r = APIRouter()

def getkintoneenv(user = Depends(get_current_user),db = Depends(get_db)):
    #db = SessionLocal()
    domain = domainService.get_default_domain(db,user.id) #get_activedomain(db, user.id)
    #db.close()
    kintoneevn = config.KINTONE_ENV(domain)
    return kintoneevn
    

def getkintoneformat(db,user = Depends(get_current_user)):
    #db = SessionLocal()
    formats = get_kintoneformat(db)
    #db.close()
    return formats


def createkintonefields(property,value,trueformat):
        p = []
        if(property=="options"):
            o=[]
            for v in value.split(','):
                o.append(f"\"{v.split('|')[0]}\":{{\"label\":\"{v.split('|')[0]}\",\"index\":\"{v.split('|')[1]}\"}}") 
            p.append(f"\"options\":{{{','.join(o)}}}")
        elif(property =="expression"):
            p.append(f"\"hideExpression\":true")
            p.append(f"\"expression\":\"{value.split(':')[1]}\"")
        elif(property =="required" or property =="unique" or property =="defaultNowValue" or property =="hideExpression" or property =="digit"):
            if str(value) == trueformat:
                p.append(f"\"{property}\":true")
            else:
                p.append(f"\"{property}\":false")
        elif(property =="protocol"):
            if(value == "メールアドレス"):
                p.append("\"protocol\":\"MAIL\"")
            elif(value == "Webサイト"):
                p.append("\"protocol\":\"WEB\"")
            elif(value == "電話番号"):
                p.append("\"protocol\":\"CALL\"")
        else:
            p.append(f"\"{property}\":\"{value}\"")
        return p

def getfieldsfromexcel(df,mapping):
    startrow = mapping.startrow
    startcolumn = mapping.startcolumn
    typecolumn = mapping.typecolumn
    codecolumn = mapping.codecolumn
    property = mapping.field.split(",")
    trueformat = mapping.trueformat
    appname = df.iloc[0,2]
    col=[]
    for row in range(startrow,len(df)):
        if pd.isna(df.iloc[row,startcolumn]):
            break
        if not df.iloc[row,typecolumn] in config.KINTONE_FIELD_TYPE:
            continue
        p=[] 
        for column in range(startcolumn,startcolumn + len(property)):
            if(not pd.isna(df.iloc[row,column])):
                propertyname =property[column-1]
                if(propertyname.find("[") == 0):
                   continue
                elif (propertyname =="remark"):
                    if (df.iloc[row,column].find("|") !=-1):
                        propertyname = "options"
                        p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat)
                    if (df.iloc[row,column] == "メールアドレス" or df.iloc[row,column] == "Webサイト" or df.iloc[row,column] == "電話番号"):
                        propertyname = "protocol"
                        p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat)
                    if (df.iloc[row,column].find("桁区切り") !=-1):
                        propertyname = "digit"
                        p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat)
                    if (df.iloc[row,column].find("前単位") !=-1):
                        propertyname = "unitPosition"
                        p = p + createkintonefields(propertyname, "BEFORE",trueformat)
                    if (df.iloc[row,column].find("後単位") !=-1):
                        propertyname = "unitPosition"
                        p = p + createkintonefields(propertyname, "AFTER",trueformat)   
                    if (df.iloc[row,column].find("単位「") !=-1):
                        propertyname = "unit"
                        ids = df.iloc[row,column].index("単位「")
                        ide = df.iloc[row,column].index("」")
                        unit = df.iloc[row,column][ids+3:ide]
                        p = p + createkintonefields(propertyname, unit,trueformat)                         
                    else:
                        continue
                elif(propertyname =="mixValue"):
                    if(df.iloc[row,column].find("レコード登録時の日") != -1):
                        propertyname = "defaultNowValue"
                        df.iloc[row,column] = trueformat
                        p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat)
                    elif(df.iloc[row,column].find("計:") != -1):
                        propertyname = "expression"
                        p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat)
                    elif(df.iloc[row,column] !=""):
                        propertyname = "defaultValue"
                        p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat)
                    else:
                        continue
                elif(propertyname=="max" or propertyname == "min"):
                    if(df.iloc[row,typecolumn] == "NUMBER"):
                        propertyname = property[column-1] + "Value"
                        p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat)
                    else:
                        propertyname = property[column-1] + "Length"
                        p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat)
                else:
                    p = p + createkintonefields(propertyname, df.iloc[row,column],trueformat)

                # if(propertyname=="options"):
                #     o=[]
                #     for v in df.iloc[row,column].split(','):
                #         o.append(f"\"{v.split('|')[0]}\":{{\"label\":\"{v.split('|')[0]}\",\"index\":\"{v.split('|')[1]}\"}}") 
                #     p.append(f"\"options\":{{{','.join(o)}}}")
                # elif(propertyname=="expression"):
                #     p.append(f"\"hideExpression\":true")
                #     p.append(f"\"expression\":{df.iloc[row,column].split(':')[1]}")
                # elif(propertyname=="required" or propertyname =="unique" or propertyname=="defaultNowValue" or propertyname=="hideExpression" or propertyname=="digit"):
                #     if (df.iloc[row,column] == trueformat):
                #         p.append(f"\"{propertyname}\":true")
                #     else:
                #         p.append(f"\"{propertyname}\":false")
                # elif(propertyname =="protocol"):
                #     if(df.iloc[row,column] == "メールアドレス"):
                #        p.append("\"protocol\":\"MAIL\"")
                #     elif(df.iloc[row,column] == "Webサイト"):
                #        p.append("\"protocol\":\"WEB\"")
                #     elif(df.iloc[row,column] == "電話番号"):
                #        p.append("\"protocol\":\"CALL\"")
                # else:
                #     p.append(f"\"{propertyname}\":\"{df.iloc[row,column]}\"")
              

        col.append(f"\"{df.iloc[row,codecolumn]}\":{{{','.join(p)}}}")
        fields = ",".join(col).replace("\\", "\\\\")
    return  json.loads(f"{{{fields}}}")  

def getsettingfromexcel(df):
    appname = df.iloc[0,2]
    des = df.iloc[2,2]
    return {"name":appname,"description":des}

def getsettingfromkintone(app:str,env:config.KINTONE_ENV):
    headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE}
    params = {"app":app}
    url = f"{env.BASE_URL}{config.API_V1_STR}/app/settings.json"
    r = httpx.get(url,headers=headers,params=params)
    return r.json()

def analysesettings(excel,kintone):
    updatesettings={}
    updates =   excel.keys() & kintone.keys()
    for key in updates:
        if excel[key] != kintone[key]:
            updatesettings[key] = excel[key]
    return updatesettings

def createkintoneapp(name:str,env:config.KINTONE_ENV):
    headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE,"Content-Type": "application/json"}
    data = {"name":name}
    url = f"{env.BASE_URL}{config.API_V1_STR}/preview/app.json"
    r = httpx.post(url,headers=headers,data=json.dumps(data))
    return r.json()

def updateappsettingstokintone(app:str,updates:dict,env:config.KINTONE_ENV):
    headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE,"Content-Type": "application/json"}
    url = f"{env.BASE_URL}{config.API_V1_STR}/preview/app/settings.json"
    data = {"app":app}
    data.update(updates)
    r = httpx.put(url,headers=headers,data=json.dumps(data))
    return r.json()

def addfieldstokintone(app:str,fields:dict,env:config.KINTONE_ENV,revision:str = None):
    headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE,"Content-Type": "application/json"}
    url = f"{env.BASE_URL}{config.API_V1_STR}/preview/app/form/fields.json"
    if revision != None:
        data = {"app":app,"revision":revision,"properties":fields}
    else:
        data = {"app":app,"properties":fields}
    r = httpx.post(url,headers=headers,data=json.dumps(data))
    r.raise_for_status()
    return r.json()
 
def updatefieldstokintone(app:str,revision:str,fields:dict,env:config.KINTONE_ENV):
    headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE,"Content-Type": "application/json"}
    url = f"{env.BASE_URL}{config.API_V1_STR}/preview/app/form/fields.json"
    data = {"app":app,"properties":fields}
    r = httpx.put(url,headers=headers,data=json.dumps(data))
    return r.json()

def deletefieldsfromkintone(app:str,revision:str,fields:dict,env:config.KINTONE_ENV):
    headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE,"Content-Type": "application/json"}
    url = f"{env.BASE_URL}{config.API_V1_STR}/preview/app/form/fields.json"
    params = {"app":app,"revision":revision,"fields":fields}
    #r = httpx.delete(url,headers=headers,content=json.dumps(params))
    r = httpx.request(method="DELETE",url=url,headers=headers,content=json.dumps(params))
    return r.json()

def deoployappfromkintone(app:str,revision:str,env:config.KINTONE_ENV):
    headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE,"Content-Type": "application/json"}
    url = f"{env.BASE_URL}{config.API_V1_STR}/preview/app/deploy.json"
    data = {"apps":[{"app":app,"revision":revision}],"revert": False}
    r = httpx.post(url,headers=headers,data=json.dumps(data))
    return r.json

# 既定項目に含めるアプリのフィールドのみ取得する
# スペース、枠線、ラベルを含まない    
def getfieldsfromkintone(app:str,env:config.KINTONE_ENV):
    headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE}
    params = {"app":app}
    url = f"{env.BASE_URL}{config.API_V1_STR}/app/form/fields.json"
    r = httpx.get(url,headers=headers,params=params)
    return r.json()

# フォームに配置するフィールドのみ取得する
# スペース、枠線、ラベルも含める
def getformfromkintone(app:str,env:config.KINTONE_ENV):
    headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE}
    params = {"app":app}
    url = f"{env.BASE_URL}{config.API_V1_STR}/form.json"
    r = httpx.get(url,headers=headers,params=params)
    return r.json()


def merge_kintone_fields(fields_response: dict, form_response: dict) -> dict:
    fields_properties = fields_response.get('properties', {})
    form_properties = form_response.get('properties', [])

    merged_properties = {k: v for k, v in fields_properties.items()}

    for index, form_field in enumerate(form_properties):
        code = form_field.get('code')
        if code:
            if code and code not in merged_properties:
                merged_properties[code] = form_field
        else:
            element_id = form_field.get('elementId')
            if element_id:
                key = element_id
                form_field['code']=element_id
                form_field['label']=form_field.get('type')
            # else:
            #     key = f"{form_field.get('type')}_{index}"
                merged_properties[key] = form_field 

    merged_response = {
        'revision': fields_response.get('revision', ''),
        'properties': merged_properties
    }
    
    return merged_response

def analysefields(excel,kintone):
    updatefields={}
    addfields={}
    delfields=[]
    updates =   excel.keys() & kintone.keys()
    adds = excel.keys() - kintone.keys()
    dels = kintone.keys() - excel.keys()
    for key in updates:
        for p in config.KINTONE_FIELD_PROPERTY:
           if excel[key].get(p) != None and kintone[key].get(p) != None and kintone[key][p] != excel[key][p]:
                updatefields[key] = excel[key]
                break
    for key in adds:
        addfields[key] = excel[key]
    for key in dels:
        if kintone[key]["type"] in config.KINTONE_FIELD_TYPE:
           delfields.append(key)

    return {"update":updatefields,"add":addfields,"del":delfields}

def getprocessfromkintone(app:str,env:config.KINTONE_ENV):
    headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE}
    params = {"app":app}
    url = f"{env.BASE_URL}{config.API_V1_STR}/app/status.json"
    r = httpx.get(url,headers=headers,params=params)
    return r.json()

def getassigneefromkintone(name,users,orgs):
    if name in ["作成者"]:
        return {"type":"ONE","entities":[{
                "entity": {
                 "type": "FIELD_ENTITY",
                 "code": name
                },
                "includeSubs": False
                }]}
    for user in users:
        if user["name"] == name:
            return {"type":"ONE","entities":[{
                "entity": {
                 "type": "USER",
                 "code": user["code"]
                },
                "includeSubs": False
                }]}
    for org in orgs:
        if org["organization"]["name"] == name:
            return {"type":"ONE","entities":[{
                "entity": {
                 "type": "ORGANIZATION",
                 "code": org["organization"]["code"]
                },
                "includeSubs": False
                }]}
    return  {"type":"ONE","entities":[]}

def getprocessfromexcel(df,users,orgs):
    begin = df[df[df.columns[1]].isin(["◆プロセス"])].index.values[0]
    status=[]
    actions=[]
    result ="{{}}"
    for row in range(begin+2,len(df)):
        n = df.iloc[row,1]
        i = df.iloc[row,0]
        a = df.iloc[row,2]
        t =  df.iloc[row,4]
        u = df.iloc[row,3]
        if pd.isna(u):
            status.append(f"\"{n}\":{{\"name\":\"{n}\",\"index\":\"{i}\",\"assignee\":{{\"type\":\"ONE\",\"entities\":[]}}}}")
        else:
            status.append(f"\"{n}\":{{\"name\":\"{n}\",\"index\":\"{i}\",\"assignee\":{json.dumps(getassigneefromkintone(u,users,orgs))}}}")
        if not pd.isna(t):
            actions.append(f"{{\"name\":\"{a}\",\"from\":\"{n}\",\"to\":\"{t}\",\"filterCond\":\"\"}}")
    result =  f"{{\"states\":{{{','.join(status)}}}, \"actions\": [{','.join(actions)}]}}"
    return json.loads(result)

def analysprocess(excel,kintone):
    excel.update({"enable":kintone["enable"],"revision":kintone["revision"]})
    diff = deepdiff.DeepDiff(excel,kintone)
    # diffstates =   excel["states"].keys() ^ kintone["states"].keys()
    # diffactions =  set(excel["actions"]).difference(set(kintone["actions"]
    
    # for item in diff:
    #     if item[0] != "enable" and item[0] != "app"  and item[0] != "revision":
    #         return True
    return diff

def updateprocesstokintone(app:str,process:dict,c:config.KINTONE_ENV):
    headers={config.API_V1_AUTH_KEY:c.API_V1_AUTH_VALUE,"Content-Type": "application/json"}
    url = f"{c.BASE_URL}{config.API_V1_STR}/preview/app/status.json"
    data = {"app":app,"enable":True}
    data.update(process)
    r = httpx.put(url,headers=headers,data=json.dumps(data))
    return r.json()

def getkintoneusers(c:config.KINTONE_ENV):
    headers={config.API_V1_AUTH_KEY:c.API_V1_AUTH_VALUE}
    url = f"{c.BASE_URL}/v1/users.json"
    r = httpx.get(url,headers=headers)
    return r.json()

def getkintoneorgs(c:config.KINTONE_ENV):
    headers={config.API_V1_AUTH_KEY:c.API_V1_AUTH_VALUE}
    params = {"code":c.KINTONE_USER}
    url = f"{c.BASE_URL}/v1/user/organizations.json"
    r = httpx.get(url,headers=headers,params=params)
    return r.json()

def uploadkintonefiles(file,env:config.KINTONE_ENV):
    if (file.endswith('alc_runtime.js') and config.DEPLOY_MODE == "DEV"):
        return {'fileKey':file}
    upload_files = {'file': open(file,'rb')}
    headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE}
    data ={'name':'file','filename':os.path.basename(file)}
    url = f"{env.BASE_URL}/k/v1/file.json"
    r = httpx.post(url,headers=headers,data=data,files=upload_files)    
    #{"name":data['filename'],'fileKey':r['fileKey']}
    return r.json()

def updateappjscss(app,uploads,env:config.KINTONE_ENV):
    dsjs = []
    dscss = []
    #mobile側
    mbjs = []  
    mbcss = []
    customize = getappcustomize(app, env)
    current_js = customize['desktop'].get('js', [])
    current_css = customize['desktop'].get('css', [])
    current_mobile_js = customize['mobile'].get('js', [])
    current_mobile_css = customize['mobile'].get('css', [])
    current_js = [item for item in current_js if not (item.get('type') == 'URL' and item.get('url', '').endswith('alc_runtime.js'))]
    for upload in uploads:
        for key in upload:
             filename = os.path.basename(key)
             if key.endswith('.js'):
                 existing_js = next((item for item in current_js 
                                     if item.get('type') == 'FILE' and  item['file']['name'] == filename 
                                    ), None)
                 if existing_js:
                    current_js = [item for item in current_js if item.get('type') == 'URL' or item['file'].get('name') != filename]
                    dsjs.append({'type':'FILE','file':{'fileKey':upload[key]}})
                 else:
                    if (key.endswith('alc_runtime.js') and config.DEPLOY_MODE == "DEV"):
                        dsjs.append({'type':'URL','url':config.DEPLOY_JS_URL})
                    else:
                        dsjs.append({'type':'FILE','file':{'fileKey':upload[key]}})
             elif key.endswith('.css'):
                existing_css = next((item for item in current_css 
                                    if item.get('type') == 'FILE' and item['file']['name'] == filename
                                ), None)
                if existing_css:
                    current_css = [item for item in current_css if item.get('type') == 'URL' or item['file'].get('name') != filename]
                    dscss.append({'type': 'FILE', 'file': {'fileKey': upload[key]}})
                else:
                    dscss.append({'type': 'FILE', 'file': {'fileKey': upload[key]}})
    #現在のJSとCSSがdsjsに追加する
    dsjs.extend(current_js)
    dscss.extend(current_css)
    mbjs.extend(current_mobile_js)
    mbcss.extend(current_mobile_css)
               
    ds ={'js':dsjs,'css':dscss}
    mb ={'js':mbjs,'css':mbcss}
    data = {'app':app,'scope':'ALL','desktop':ds,'mobile':mb,'revision':customize["revision"]}
    headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE,"Content-Type": "application/json"}
    url = f"{env.BASE_URL}{config.API_V1_STR}/preview/app/customize.json"
    print(json.dumps(data))
    r = httpx.put(url,headers=headers,data=json.dumps(data))
    return r.json()

#kintone カスタマイズ情報
def getappcustomize(app,env:config.KINTONE_ENV):
    headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE}
    url = f"{env.BASE_URL}{config.API_V1_STR}/preview/app/customize.json"
    params = {"app":app}
    r = httpx.get(url,headers=headers,params=params)
    return r.json()
    

def getTempPath(filename):
    scriptdir = Path(__file__).resolve().parent
    rootdir = scriptdir.parent.parent.parent.parent
    fpath = os.path.join(rootdir,"Temp",filename)
    return fpath

def createappjs(domain_url,app,db):
    #db = SessionLocal()
    flows = appService.get_flow(db,domain_url,app) #get_flows_by_app(db,domain_url,app)
    #db.close()
    content={}
    for flow in flows:
        content[flow.eventid] = {'flowid':flow.flowid,'name':flow.name,'content':flow.content}
    js = 'const alcflow=' + json.dumps(content)
    # scriptdir = Path(__file__).resolve().parent
    # rootdir = scriptdir.parent.parent.parent.parent
    # fpath = os.path.join(rootdir,"Temp",f"alc_setting_{app}.js")
    fpath = getTempPath(f"alc_setting_{app}.js")
    print(fpath)
    with open(fpath,'w') as file:
        file.write(js)
    return fpath

@r.post("/test",)
async def test(file:UploadFile= File(...),app:str=None):
    if file.filename.endswith('.xlsx'):
        try:
            content = await file.read()
            df = pd.read_excel(BytesIO(content))
            users = getkintoneusers()
            orgs =  getkintoneorgs()
            # excel = getprocessfromexcel(df)
            # kintone = getprocessfromkintone(app)
            # process = analysprocess(excel,kintone)
            test = getprocessfromexcel(df,users["users"], orgs["organizationTitles"])
            # excel =  getfieldsfromexcel(df)
            # if(app != None):
            #     kintone = getfieldsfromkintone(app)
            #     fields = analysefields(excel,kintone["properties"])                             
        except Exception as e:
            raise HTTPException(status_code=400, detail=f"Error occurred while parsing file {file.filename}")
    else:
        raise HTTPException(status_code=400, detail=f"File {file.filename} is not an Excel file")
       
    return test 


@r.get("/group")
async def group(request:Request,kintoneurl:str,kintoneuser:str,kintonepwd:str):
    try:
        auth_value = base64.b64encode(bytes(f"{kintoneuser}:{kintonepwd}","utf-8"))
        headers={config.API_V1_AUTH_KEY:auth_value}
        url = f"{kintoneurl}/v1/user/groups.json?code={kintoneuser}"
        r = httpx.get(url,headers=headers)
        return r.json()
    except Exception as e:
        raise APIException('kintone:group',request.url._url, f"Error occurred while get group(url:{kintoneurl} user:{kintoneuser}):",e)  
    
@r.post("/download",)
async def download(request:Request,key,c:config.KINTONE_ENV=Depends(getkintoneenv)):
    try:
        headers={config.API_V1_AUTH_KEY:c.API_V1_AUTH_VALUE}
        params = {"fileKey":key}
        url = f"{c.BASE_URL}/k/v1/file.json"
        r = httpx.get(url,headers=headers,params=params)
        return r.json()
    except Exception as e:
        raise APIException('kintone:download',request.url._url,f"Error occurred while download file.json:",e)

@r.post("/upload")
async def upload(request:Request,files:t.List[UploadFile] = File(...)):
    dataframes = []
    for file in files:
        if file.filename.endswith('.xlsx'):
            try:
                content = await file.read()
                df = pd.read_excel(BytesIO(content))
                print(df)
                dataframes.append(df)
            except Exception as e:
                raise APIException('kintone:upload',request.url._url,f"Error occurred while uploading file {file.filename}:",e)
        else:
            raise APIException('kintone:upload',request.url._url, f"File {file.filename} is not an Excel file",e)
       
    return {"files": [file.filename for file in files]}  

@r.post("/updatejscss")
async def jscss(request:Request,app:str,files:t.List[UploadFile] = File(...),env:config.KINTONE_ENV = Depends(getkintoneenv)):
    try:
        jscs=[]
        for file in files:
            fbytes = file.file.read()
            fname = file.filename
            fpath =  '{}\\{}'.format('Temp',fname)
            fout = open(fpath,'wb')
            fout.write(fbytes)
            fout.close()
            upload = uploadkintonefiles(fpath,env)
            if upload.get('fileKey') != None:
                jscs.append({ file.filename:upload['fileKey']})
        appjscs = updateappjscss(app,jscs,env)
        if appjscs.get("revision") != None:
           deoployappfromkintone(app,appjscs["revision"],env)
           return appjscs
    except Exception as e:
        raise APIException('kintone:updatejscss',request.url._url, f"Error occurred while update js/css {file.filename} is not an Excel file",e)

@r.get("/app")
async def app(request:Request,app:str,env:config.KINTONE_ENV=Depends(getkintoneenv)):
    try:
        headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE}
        url = f"{env.BASE_URL}{config.API_V1_STR}/app.json"
        params ={"id":app}
        r = httpx.get(url,headers=headers,params=params)
        return r.json()
    except Exception as e:
        raise APIException('kintone:app',request.url._url, f"Error occurred while get app({env.DOMAIN_NAME}->{app}):",e)   

@r.get("/allapps")
async def allapps(request:Request,env:config.KINTONE_ENV=Depends(getkintoneenv)):
    try:
        headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE}
        url = f"{env.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
        return {"apps": all_apps}

    except Exception as e:
        raise APIException('kintone:allapps', request.url._url, f"Error occurred while get allapps({env.DOMAIN_NAME}):", e)

@r.get("/appfields")
async def appfields(request:Request,app:str,env:config.KINTONE_ENV = Depends(getkintoneenv)):
    try:
        return getfieldsfromkintone(app,env)
    except Exception as e:
       raise APIException('kintone:appfields',request.url._url, f"Error occurred while get app fileds({env.DOMAIN_NAME}->{app}):",e) 

@r.get("/allfields")
async def allfields(request:Request,app:str,env:config.KINTONE_ENV = Depends(getkintoneenv)):
    try:
        field_resp = getfieldsfromkintone(app,env)
        form_resp = getformfromkintone(app,env)
        return merge_kintone_fields(field_resp,form_resp)
    except Exception as e:
       raise APIException('kintone:allfields',request.url._url, f"Error occurred while get form fileds({env.DOMAIN_NAME}->{app}):",e) 

@r.get("/appprocess")
async def appprocess(request:Request,app:str,env:config.KINTONE_ENV = Depends(getkintoneenv)):
    try:
        return getprocessfromkintone(app,env)
    except Exception as e:
       raise APIException('kintone:appprocess',request.url._url, f"Error occurred while get app process({env.DOMAIN_NAME}->{app}):",e) 

@r.get("/alljscss")
async def alljscs(request:Request,app:str,env:config.KINTONE_ENV=Depends(getkintoneenv)):
    try:
        headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE}
        url = f"{env.BASE_URL}{config.API_V1_STR}/app/customize.json"
        params = {"app":app}
        r = httpx.get(url,headers=headers,params=params)
        return r.json()
    except Exception as e:
       raise APIException('kintone:alljscss',request.url._url, f"Error occurred while get app js/css({env.DOMAIN_NAME}->{app}):",e) 

@r.post("/createapp",)
async def createapp(request:Request,name:str,env:config.KINTONE_ENV=Depends(getkintoneenv)):
    try:
        headers={config.API_V1_AUTH_KEY:env.API_V1_AUTH_VALUE,"Content-Type": "application/json"}
        data = {"name":name}
        url = f"{env.BASE_URL}{config.API_V1_STR}/preview/app.json"
        r = httpx.post(url,headers=headers,data=json.dumps(data))
        result = r.json()
        if result.get("app") != None:
            url = f"{env.BASE_URL}{config.API_V1_STR}/preview/app/deploy.json"
            data = {"apps":[result],"revert": False}
            r = httpx.post(url,headers=headers,data=json.dumps(data))
        return r.json
    except Exception as e:
        raise APIException('kintone:createapp',request.url._url, f"Error occurred while create app({env.DOMAIN_NAME}->{name}):",e) 

@r.get("/defaultgroup")
async def currentgroup(request:Request,env:config.KINTONE_ENV=Depends(getkintoneenv)):
    try:
        auth_value = env.API_V1_AUTH_VALUE
        headers={config.API_V1_AUTH_KEY:auth_value}
        url = f"{env.BASE_URL}/v1/user/groups.json?code={env.KINTONE_USER}"
        r = httpx.get(url,headers=headers)
        return r.json()
    except Exception as e:
        raise APIException('kintone:currentgroup',request.url._url, f"Error occurred while get default domain group(domain:{env.DOMAIN_NAME} url:{env.BASE_URL} user:{env.KINTONE_USER}):",e)  
    
@r.post("/createappfromexcel",)
async def createappfromexcel(request:Request,files:t.List[UploadFile] = File(...),format:int = 0,env = Depends(getkintoneenv),db = Depends(get_db)):
    try:
        mapping = getkintoneformat(db)[format]
    except Exception as e:
        raise APIException('kintone:createappfromexcel',request.url._url, f"Error occurred while get kintone format:",e)

    for file in files:
        if file.filename.endswith('.xlsx'):
            try:
                content = await file.read()
                df = pd.read_excel(BytesIO(content))
               #アプリ名
                appname = df.iloc[0,2]
                desc = df.iloc[2,2] 
                result = {"app":0,"revision":0,"msg":""}
                fields = getfieldsfromexcel(df,mapping)
                users = getkintoneusers(env)
                orgs =  getkintoneorgs(env)
                processes = getprocessfromexcel(df,users["users"], orgs["organizationTitles"])
                app = createkintoneapp(appname,env)
                if app.get("app") != None:
                    result["app"] = app["app"]
                    app = updateappsettingstokintone(result["app"],{"description":desc},env)
                if app.get("revision") != None:
                    result["revision"] = app["revision"]
                    app = addfieldstokintone(result["app"],fields,env)
                if len(processes)> 0:
                    app = updateprocesstokintone(result["app"],processes,env)
                if app.get("revision") != None:
                    result["revision"] = app["revision"]
                    deoployappfromkintone(result["app"],result["revision"],env)
            except Exception as e:
                raise APIException('kintone:createappfromexcel',request.url._url, f"Error occurred while parsing file ({env.DOMAIN_NAME}->{file.filename}):",e)
        else:
            raise APIException('kintone:createappfromexcel',request.url._url, f"File {file.filename} is not an Excel file",e)   
    return result


@r.post("/updateappfromexcel")
async def updateappfromexcel(request:Request,app:str,files:t.List[UploadFile] = File(...),format:int = 0,env = Depends(getkintoneenv),db = Depends(get_db)):
    try:
        mapping = getkintoneformat(db)[format]
    except Exception as e:
        raise APIException('kintone:updateappfromexcel',request.url._url, f"Error occurred while get kintone format:",e)
    
    for file in files:
        if file.filename.endswith('.xlsx'):
            try:
                content = await file.read()
                df = pd.read_excel(BytesIO(content))
                excel = getsettingfromexcel(df)
                kintone= getsettingfromkintone(app,env)
                settings = analysesettings(excel,kintone)
                excel = getfieldsfromexcel(df,mapping)
                kintone = getfieldsfromkintone(app,env)
                users = getkintoneusers(env)
                orgs =  getkintoneorgs(env)
                exp = getprocessfromexcel(df,users["users"], orgs["organizationTitles"])
                #exp = getprocessfromexcel(df)
                kinp = getprocessfromkintone(app,env)
                process = analysprocess(exp,kinp)
                revision = kintone["revision"]
                fields = analysefields(excel,kintone["properties"])
                result = {"app":app,"revision":revision,"msg":"No Update"}
                deploy = False
                if len(fields["update"]) > 0:
                    result = updatefieldstokintone(app,revision,fields["update"],env)
                    revision = result["revision"]
                    deploy = True
                if len(fields["add"]) > 0:
                    result = addfieldstokintone(app,fields["add"],env,revision)
                    revision = result["revision"]
                    deploy = True
                if len(fields["del"]) > 0:
                    result = deletefieldsfromkintone(app,revision,fields["del"],env)
                    revision = result["revision"]
                    deploy = True
                if len(settings) > 0:
                    result = updateappsettingstokintone(app,settings,env)
                    revision = result["revision"]
                    deploy = True
                if len(process)>0:
                    result = updateprocesstokintone(app,exp,env)
                    revision = result["revision"]
                    deploy = True
                if deploy:
                    result = deoployappfromkintone(app,revision,env)
            except Exception as e:
                raise APIException('kintone:updateappfromexcel',request.url._url, f"Error occurred while parsing file ({env.DOMAIN_NAME}->{file.filename}):",e)
        else:
            raise APIException('kintone:updateappfromexcel',request.url._url, f"File {file.filename} is not an Excel file",e)   
    return result

@r.post("/updateprocessfromexcel",)
async def updateprocessfromexcel(request:Request,app:str,env = Depends(getkintoneenv)):
   
    try:
        excel = getprocessfromexcel()
        kintone = getprocessfromkintone(app,env)
        revision = kintone["revision"]
        #fields = analysefields(excel,kintone["properties"])
        result = {"app":app,"revision":revision,"msg":"No Update"}
        deploy = False
        # if len(fields["update"]) > 0:
        #     result = updatefieldstokintone(app,revision,fields["update"])
        #     revision = result["revision"]
        #     deploy = True
        # if len(fields["add"]) > 0:
        #     result = addfieldstokintone(app,fields["add"],revision)
        #     revision = result["revision"]
        #     deploy = True
        # if len(fields["del"]) > 0:
        #     result = deletefieldsfromkintone(app,revision,fields["del"])
        #     revision = result["revision"]
        #     deploy = True
        # if len(settings) > 0:
        #     result = updateappsettingstokintone(app,settings)
        #     revision = result["revision"]
        #     deploy = True
        result = updateprocesstokintone(app,excel,env)
        revision = result["revision"]
        deploy = True
        if deploy:
            result = deoployappfromkintone(app,revision,env)
    except Exception as e:
        raise APIException('kintone:updateprocessfromexcel',request.url._url, f"Error occurred while update process ({env.DOMAIN_NAME}->{app}):",e)
       
    return result


@r.post("/createjstokintone",)
async def createjstokintone(request:Request,app:str,env:config.KINTONE_ENV = Depends(getkintoneenv),db = Depends(get_db)):
    try:
        jscs=[]
        files=[]
        files.append(createappjs(env.BASE_URL, app, db))
        files.append(getTempPath('alc_runtime.js'))
        files.append(getTempPath('alc_runtime.css'))        
        for file in files:
            upload = uploadkintonefiles(file,env)
            if upload.get('fileKey') != None:
                print(upload)
                jscs.append({ file :upload['fileKey']})
        appjscs = updateappjscss(app,jscs,env)
        if appjscs.get("revision") != None:
           deoployappfromkintone(app,appjscs["revision"],env)
           return appjscs
    except Exception as e:
        raise APIException('kintone:createjstokintone',request.url._url, f"Error occurred while create js ({env.DOMAIN_NAME}->{app}):",e)
