from fastapi import APIRouter, Form, Depends, HTTPException, File, UploadFile
from typing import List,Optional,Union
from fastapi.responses import FileResponse
from random import randint
from fastapi.security import OAuth2PasswordRequestForm
from app.models.models import User,Favorite_course,News,Article_list
from app.api import deps
from sqlalchemy.orm import Session
from typing import Any, Dict
import secrets
from fastapi_login.exceptions import InvalidCredentialsException
from fastapi_login import LoginManager
from datetime import timedelta,datetime
from jose import jwt
from emails.template import JinjaTemplate
from tortoise.queryset import Q
from fastapi.responses import HTMLResponse

news = APIRouter()

IMAGEDIR = "/var/www/ntcri/assets/news_files/"
IMAGEDIR_short = "assets/news_files/"

@news.get("/get_news")
async def search_news(
    news_id : int = None,
    category :Optional[str] = None,
    page_num : Optional[int] = None,
    page_amount : Optional[int] = None
):
    try:
        news_list = News.all()
        if news_id :
            news_list = news_list.filter(id=news_id).all()
        
        if category:
            news_list = news_list.filter(category=category).all()

        count = await news_list.all().count()

        if page_num and page_amount:
            news_list = news_list.offset((page_num-1)*page_amount).limit(page_amount)
        
        news_list = await news_list.all().order_by("-create_time")

        news_objs = []
        for news_obj in news_list:
            try:
                news_tmp = {
                    "news_id": news_obj.id,
                    "title": news_obj.title,
                    "category": news_obj.category,
                    "create_time" : news_obj.create_time,
                    "click_time" : news_obj.click_time,
                    "content" : news_obj.content,
                    "files" : news_obj.files,
                    "URL" : news_obj.URL,
                    "tags" : news_obj.tags,
                    "cover_img": news_obj.cover_img
                }
            except:
                news_tmp = {"msg":"data wrong"}
                
            news_objs.append(news_tmp)

        return {"msg": "success", "code": 200, "total_num" : count,"news": news_objs}
    except Exception as e:
        return {"msg": str(e), "code": 500}
    

async def create_upload_files(files:Optional[List[UploadFile]] = File(None)):
    files_url = {}
    if files :
        file_num = 1
        print(file_num)
        for file in files:
            contents = await file.read()

            #save the file
            with open(f"{IMAGEDIR}{file.filename}", "wb") as f:
                f.write(contents)
                file_name = "file" + str(file_num)
                print(file_name)
                files_url[file_name]=f"{IMAGEDIR_short}{file.filename}"       
                file_num=file_num+1 

    return files_url

@news.post("/insert_news_imgs")
async def insert_imgs(
    files_url = Depends(create_upload_files)
):
    try:
        files = str(files_url),
        
        return {"msg": "success", "code": 200, "url": files}
    except Exception as e:
        return {"msg": str(e), "code": 500}

@news.post("/insert_news")
async def insert_news(
    title : str = Form(default=''),
    category : str = Form(default=''),
    content : str = Form(default=''),
    URL :str = Form(default=''),
    tags : str = Form(default='[]'),
    files_url = Depends(create_upload_files),
    create_time :str = Form(default=datetime.now()),
    cover_img_file:UploadFile = File(default='')
):
    try:
        cover_img = ''
        if cover_img_file != '':
            contents = await cover_img_file.read()

        #save the file
            with open(f"{IMAGEDIR}{cover_img_file.filename}", "wb") as f:
                f.write(contents)
        
            cover_img = f"{IMAGEDIR_short}{cover_img_file.filename}"

        new_news = await News.create(
            title=title,
            category=category,
            content=content,
            create_time = create_time,
            files = str(files_url),
            URL = URL,
            tags = tags,
            cover_img = cover_img
        )
        
        return {"msg": "success", "code": 200, "new_news": new_news.id}
    except Exception as e:
        return {"msg": str(e), "code": 500}

@news.post("/update_news")
async def update_news(
    news_id : int = Form(default=0),
    title : str = Form(default=''),
    category : str = Form(default=''),
    create_time :str = Form(default=datetime.now()),
    content : str = Form(default=''),
    URL :str = Form(default=''),
    tags : str = Form(default='[]'),
    files_url = Depends(create_upload_files),
    cover_img_file:UploadFile = File(default=''),
):
    try:
        if news_id == 0 :
            return {"msg": "no ID"}
        
        news_obj = await News.get(id=news_id)

        if title.strip() != '':
            news_obj.title = title
        
        if category.strip() != '':
            news_obj.category = category

        if create_time != '':
            news_obj.create_time = create_time

        if content.strip() != '':
            news_obj.content = content

        if URL.strip() != '':
            news_obj.URL = URL

        if tags != '[]':
            news_obj.tags = tags

        
        if cover_img_file != '':
            contents = await cover_img_file.read()

            with open(f"{IMAGEDIR}{cover_img_file.filename}", "wb") as f:
                f.write(contents)
        
            news_obj.cover_img = f"{IMAGEDIR_short}{cover_img_file.filename}"
        
        news_obj.files = str(files_url)
        
        await news_obj.save()
        
        return {"msg": "success", "code": 200}
    except Exception as e:
        return {"msg": str(e), "code": 500}

@news.post("/delete_news")
async def delete_news(id: int = 0):
    if id != 0:
        await News.filter(id=id).delete()
        return {"msg": "success", "code": 200}
    else :
        return {"msg": "please input ID", "code": 200}
    
@news.get("/search_news_like")
async def search_class_like(keyword: str):
    try:
        news_list = await News.filter(
            Q(title__icontains=keyword)|
            Q(category__icontains=keyword)|
            Q(content__icontains=keyword)|
            Q(tags__icontains=keyword)
                ).all()
        
        news_objs = []
        for news_obj in news_list:
            news_tmp = {
            "news_id": news_obj.id,
            "title": news_obj.title,
            "category": news_obj.category,
            "create_time" : news_obj.create_time,
            "click_time" : news_obj.click_time,
            "content" : news_obj.content,
            "files" : news_obj.files,
            "URL" : news_obj.URL,
            "tags" : news_obj.tags,
            "cover_img": news_obj.cover_img
        }
            news_objs.append(news_tmp)

        return {"msg": "success", "code": 200, "news": news_objs}
    except Exception as e:
        return {"msg": str(e), "code": 500}
    

    