#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from fastapi import APIRouter, Request, Depends,Response,HTTPException,status,Query,UploadFile,File,Form
from typing import List, Optional
from fastapi.responses import JSONResponse
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session
from database import get_db
from config import settings
from urllib import parse
# from PIL import Image
from models import *
from utils import *

import requests
import hashlib
import random
import string
import json
import time
import os


router = APIRouter()

UPLOAD_IMAGE_PATH = '/data/upload/img/'
UPLOAD_mergefile_PATH = '/data/upload/mergefile/'

@router.post("/upload/upload_img")
async def upload_img(
        request: Request,
        file: UploadFile = File(...),
        db: Session = Depends(get_db)
):
    file_name = file.filename

    # 文件后续名校验
    suffix = os.path.splitext(file_name)[-1]
    if suffix.lower() not in ['.png', '.jpg', '.jpeg']:
        return {
            'code': 1,
            'msg': '文件类型不在png,jpg范围内',
        }

    upload_path = UPLOAD_IMAGE_PATH
    file_dir = os.path.join(upload_path, "{}".format("poster"))
    if os.path.exists(file_dir) == False:
        os.makedirs(file_dir)

    file_name = new_guid() + suffix.lower()
    file_path = os.path.abspath("{}/{}".format(file_dir, file_name))
    if os.path.exists(file_path):
        os.remove(file_path)

    content = await file.read()
    with open(file_path, 'wb') as f:
        f.write(content)

    print('file_path:', file_path)

    return {
        'code': 0,
        'msg': '上传成功',
        'data': file_name
    }


@router.get('/get_img/get_img_by_id/{id}', response_class=FileResponse)
async def get_poster_by_id(
        request: Request,
        id: str,
        db: Session = Depends(get_db)
):
    image_filepath = os.path.abspath(os.path.join(UPLOAD_IMAGE_PATH+'poster/', id )) #+ ".png"
    # print(image_filepath)
    if os.path.exists(image_filepath) == False:
        return {'err':'错误'}
        image_filepath = "./static/img/video_poster.png"
    # else:
    #     file_size = os.path.getsize(image_filepath)
        # if file_size > (1024 * 1024 * 1.5):  # 1.5M
        #     image = Image.open(image_filepath)
        #     image.thumbnail((675, 390))
        #     image.save(image_filepath, 'png')

    return FileResponse(image_filepath)


@router.post("/upload/uploadfile")
async def upload_big_file(        request: Request,
                                  file: UploadFile = File(...),
                                  chunknumber: str = Query(''),
                                  identifier: str = Query('')):  # 分片上传文件【用唯一标志符+分片序号】作为文件名
    if not file:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="文件字段缺失")
    if len(chunknumber) == 0 or len(identifier) == 0:
        return {"eroor": "没有传递相关参数"}
    print(1111)
    task = identifier  # 获取文件唯一标识符
    chunk = chunknumber  # 获取该分片在所有分片中的序号【客户端设定】
    filename = '%s%s' % (task, chunk)  # 构成该分片唯一标识符
    file_dir = f"{UPLOAD_mergefile_PATH}/uploads/"
    if os.path.exists(file_dir) == False:
        os.makedirs(file_dir)
    contents = await file.read()  # 异步读取文件
    with open(file_dir+f"{filename}", "wb") as f:
        f.write(contents)
    return {"filename": file.filename}



@router.post("/upload/mergefile")
async def mergefile(identifier: str = Query(''),
                    filename: str = Query(''),
                    chunkstar: int = Query(0)):  # 根据唯一标识符合并文件
    if len(filename) == 0 or len(identifier) == 0:
        return {"eroor": "没有传递相关参数"}
    suffix = os.path.splitext(filename)[-1]
    filename = new_guid() + suffix.lower()
    target_filename = filename  # 获取上传文件的文件名【保存的文件名】
    task = identifier  # 获取文件的唯一标识符
    chunk = chunkstar  # 分片序号开始的序号默认=0
    if os.path.isfile(f"{UPLOAD_mergefile_PATH}/uploads/{target_filename}"):  # 如果客户端传递过来的文件名在服务器上已经存在，那么另外新建一个【时间戳.后缀名】文件
        t = time.time()  # 时间戳
        timeUnix = str(round(t * 1000))  # 毫秒级时间戳
        filesuffix = os.path.splitext(target_filename)[1]  # 后缀名
        target_filename = timeUnix + filesuffix  # 新文件名【时间戳.后缀名】
    error_i = 0
    chunkfilename = ""
    with open(f"{UPLOAD_mergefile_PATH}/uploads/{target_filename}", 'wb') as target_file:  # 创建新文件
        while True:  # 循环把分片文件写入新建的文件
            if os.path.isfile(f"{UPLOAD_mergefile_PATH}/uploads/{task}{chunk}"):  # 存在这个文件
                try:
                    # 分片文件名
                    chunkfilename = f"{UPLOAD_mergefile_PATH}/uploads/{task}{chunk}"
                    # 按序打开每个分片
                    source_file = open(chunkfilename, 'rb')
                    # 读取分片内容写入新文件
                    target_file.write(source_file.read())
                    source_file.close()
                except IOError:  # 当分片标志chunk累加到最后，文件夹里面不存在{task}{chunk}文件时，退出循环
                    break
                os.remove(f"{UPLOAD_mergefile_PATH}/uploads/{task}{chunk}")  # 删除分片文件
            else:  # 【如果分片文件上传中途出错，导致中间缺少某个分片文件，跳过它，不退出循环，直到累计缺少次数大于3次，再跳出循环】
                error_i += 1
                if error_i > 3:
                    break
            chunk += 1
    os.chmod(f"{UPLOAD_mergefile_PATH}uploads/{target_filename}", 0o664)  # linux设置权限0o664、0o400
    return {"code": 200, "filename": f"{target_filename}"}


@router.get("/download/{filename}")
async def download_file(filename: str):
    """
    根据提供的文件名下载文件。
    :param filename: 要下载的文件的名称。
    """
    try:
        # 构造文件的完整路径
        file_path = os.path.join(UPLOAD_mergefile_PATH, 'uploads/', filename)

        # 检查文件是否存在
        if not os.path.isfile(file_path):
            raise HTTPException(status_code=404, detail="文件未找到")

        # 设置文件头部和内容类型
        headers = {
            'Content-Disposition': f'attachment; filename={filename}'
        }

        # 使用FileResponse返回文件流
        return FileResponse(
            path=file_path,
            headers=headers,
            media_type='application/octet-stream'  # 可以按需更改为适当的MIME类型
        )

    except HTTPException as e:
        raise e
    except Exception as e:
        # 处理其他异常情况
        raise HTTPException(status_code=500, detail=str(e))