from rest_framework.views import APIView
from rest_framework.response import Response
from smartfarming.models.ascend import MongoBase, MongoLandInfo, MongoPlantInfo, MongoAreaJob, LandPlanInfo, CountryModel, PlanWeekend
from smartfarming.models.user import DeviceUser
from smartfarming.serializers.ascend_serializers import (
    BaseSerializers, 
    MongoLandInfoSerializers, 
    MongoPlantInfoSerializers, 
    MongoAreaJobSerializers,
    CountryModelSerializers,
    PlanWeekendSerializers,
    MongoPlanWeekendSerializers,
    LandPlanInfoSerializers
)
from django.core.paginator import Paginator
import time
import datetime
from django.db.models import Q, Count


class BaseAPIView(APIView):

    def post(self, request):
        # 基地列表
        query = MongoBase.objects.all().first()
        serializers = BaseSerializers(query)
        return Response({"code": 0, "msg": "success", "data": serializers.data})


class BaseUpdateAPIView(APIView):

    def post(self, request):
        # 基地更新
        request_data = request.data 
        base_phone = request_data.get("base_phone")
        base_name = request_data.get("base_name")
        base_img = request_data.get("base_img")
        base_charge = request_data.get("base_charge")
        try:
            MongoBase.objects.all().update(
                base_name=base_name,
                base_charge=base_charge,
                base_phone=base_phone,
                base_img=base_img
            )
            return Response({"code": 0, "msg": "success"})
        except Exception as e:
            return Response({"code": 0, "msg": "更新信息失败"})
        

class MongoLandInfoAPIView(APIView):

    def post(self, request):
        # 地块列表
        request_data = request.data 
        page_num = int(request_data.get("pagenum")) if request_data.get("pagenum") else 1
        page_size = int(request_data.get("pagesize")) if request_data.get("pagesize") else 10
        queryset = MongoLandInfo.objects.filter(is_delete=1).order_by("-uptime")
        total_obj = queryset.count()
        paginator = Paginator(queryset, page_size)
        page_obj = paginator.get_page(page_num)
        serializers = MongoLandInfoSerializers(page_obj, many=True)
        return Response({"code": 0, "msg": "success", "data": serializers.data, "count": total_obj})
    


class MongoAreaJobDetailAPIView(APIView):

    def post(self, request):
        # 农事详情
        request_data = request.data 
        land_id = request_data.get("land_id")
        query_date = request_data.get("query_date")
        page_num = int(request_data.get("pagenum")) if request_data.get("pagenum") else 1
        page_size = int(request_data.get("pagesize")) if request_data.get("pagesize") else 10
        if query_date:
            start = int(query_date[0]/1000)
            end = int(query_date[1]/1000)
            queryset = MongoAreaJob.objects.filter(land=land_id).filter(uptime__gte=start, uptime__lte=end).order_by("-uptime")
        else:
            queryset = MongoAreaJob.objects.filter(land=land_id).order_by("-uptime")
        total_obj = queryset.count()
        paginator = Paginator(queryset, page_size)
        page_obj = paginator.get_page(page_num)
        serializers = MongoAreaJobSerializers(page_obj, many=True)
        return Response({"code": 0, "msg": "success", "data": serializers.data, "count": total_obj})
    

class MongoAreaJobAddAPIView(APIView):
    def post(self, request):
        # 农事新增
        request_data = request.data 
        land_id = request_data.get("land_id")
        batch = request_data.get("batch")
        jobname = request_data.get("jobname")
        uptime = int(request_data.get("uptime"))
        MongoAreaJob.objects.create(
            land=land_id,
            batch=batch,
            jobname=jobname,
            uptime=uptime
        )
        return Response({"code": 0, "msg": "新增农事成功"})


class MongoLandInfoAddAPIView(APIView):

    def post(self, request):
        # 地块新增
        request_data = request.data 
        farm = request_data.get("farm")
        landname = request_data.get("landname")
        user = request_data.get("user")
        landaddr = request_data.get("landaddr")
        landarea = request_data.get("landarea")
        tel = request_data.get("tel")
        try:
            land = MongoLandInfo.objects.filter(farm=farm, is_delete=1)
            if land:
                return Response({"code": 2, "msg": "该地块编号已存在，请修改"})
            land = MongoLandInfo.objects.create(
                farm = farm,
                landname = landname,
                user = user,
                landaddr=landaddr,
                landarea=landarea,
                tel = tel,
                uptime = int(time.time())
            )
            # 新增地块后初始化一个农事
            if land:
                LandPlanInfo.objects.create(
                    land_id=land.id,
                    addtime=int(time.time())
                )
            return Response({"code": 0, "msg": "新增地块成功"})
        except Exception as e:
            print(e)
            return Response({"code": 2, "msg": "新增地块失败"})
    

class MongoLandInfoUpdateAPIView(APIView):

    def post(self, request):
        # 地块更新
        request_data = request.data 
        land_id = request_data.get("land_id")
        landname = request_data.get("landname")
        user = request_data.get("user")
        tel = request_data.get("tel")
        MongoLandInfo.objects.filter(id=land_id).update(
            landname = landname,
            user = user,
            tel = tel,
            uptime = int(time.time())
        )
        return Response({"code": 0, "msg": "更新地块成功"})


class MongoLandInfoDeleteAPIView(APIView):

    def post(self, request):
        # 地块删除
        request_data = request.data 
        land_id = request_data.get("land_id")
        try:
            # 核对是否在该地块存在未完成的种植
            land_plan = LandPlanInfo.objects.filter(land_id=land_id, recovery_time=0).exclude(plan_id=0)
            if land_plan.count():
                return Response({"code": 2, "msg": "该地块存在未完成的种植任务,请核对"})
            MongoLandInfo.objects.filter(id=land_id).update(is_delete=0)
            return Response({"code": 0, "msg": "删除地块成功"})
        except Exception as e:
            return Response({"code": 2, "msg": "删除地块失败"})


class MongoPlantInfoAPIView(APIView):

    def post(self, request):
        # 作物列表
        request_data = request.data 
        plantname = request_data.get("plantname")
        page_num = int(request_data.get("pagenum")) if request_data.get("pagenum") else 1
        page_size = int(request_data.get("pagesize")) if request_data.get("pagesize") else 10
        if plantname:
            queryset = MongoPlantInfo.objects.filter(is_delete=1, plantname__icontains=plantname).order_by("-uptime")
        else:
            queryset = MongoPlantInfo.objects.filter(is_delete=1).order_by("-uptime")
        total_obj = queryset.count()
        paginator = Paginator(queryset, page_size)
        page_obj = paginator.get_page(page_num)
        serializers = MongoPlantInfoSerializers(page_obj, many=True)
        return Response({"code": 0, "msg": "success", "data": serializers.data, "count": total_obj})
    
class PlanDetailAPIView(APIView):

    def post(self, request):
        # 作物详情
        request_data = request.data
        plan_id = request_data.get("plan_id")
        queryset = MongoPlantInfo.objects.get(id=plan_id)
        serializers = MongoPlanWeekendSerializers(queryset)
        return Response({"code": 0, "msg": "success", "data": serializers.data}) 


class MongoPlantInfoAddAPIView(APIView):

    def post(self, request):
        # 作物新增
        request_data = request.data 
        batch = request_data.get("batch")
        plantname = request_data.get("plantname")
        pickcode = request_data.get("pickcode")
        planttype = request_data.get("planttype")
        plan = MongoPlantInfo.objects.filter(plantname=plantname, planttype=planttype)
        if plan:
            return Response({"code": 2, "msg": "该作物种类已存在，请核查"})
        plan_id = MongoPlantInfo.objects.create(
            batch = batch,
            plantname = plantname,
            pickcode = pickcode,
            planttype = planttype,
            uptime = int(time.time())
        )
        if plan_id:
            cycle_list = request_data.get("cycle_list")
            for c in cycle_list:
                PlanWeekend.objects.create(
                    plan_id=plan_id.id,
                    name=c.get("name"),
                    start_time=c.get("time")[0],
                    end_time=c.get("time")[1],
                    pest=",".join([str(i) for i in c.get("pest")]),
                    pick=",".join([str(i) for i in c.get("pick")]),
                    mark=c.get("mark")
                )
        return Response({"code": 0, "msg": "新增作物及周期成功"})
        

class MongoPlantInfoUpdateAPIView(APIView):

    def post(self, request):
        # 作物更新
        request_data = request.data
        plan_id = request_data.get("crop_id")
        batch = request_data.get("batch")
        plantname = request_data.get("plantname")
        pickcode = request_data.get("pickcode")
        planttype = request_data.get("planttype")
        plan = MongoPlantInfo.objects.filter(plantname=plantname, planttype=planttype)
        if plan:
            return Response({"code": 2, "msg": "该作物种类已存在，请核查"})
        MongoPlantInfo.objects.filter(id=plan_id).update(
            batch = batch,
            plantname = plantname,
            pickcode = pickcode,
            planttype = planttype,
            uptime = int(time.time())
        )
        cycle_list = request_data.get("cycle_list")
        for c in cycle_list:
            id = c.get("id", "")
            name = c.get("name")
            start_time = (c.get("time"))[0]
            end_time = (c.get("time"))[1]
            pest_lst = [str(i) for i in c.get("pest")]
            pest = ",".join(pest_lst)
            pick_lst = [str(i) for i in c.get("pick")]
            pick = ",".join(pick_lst)
            mark = c.get("mark")
            if id:
                PlanWeekend.objects.filter(id=id, plan_id=plan_id).update(
                    name=name,
                    start_time=start_time,
                    end_time=end_time,
                    pest=pest,
                    pick=pick,
                    mark=mark
                )
            else:
                PlanWeekend.objects.create(
                    name=name,
                    plan_id=plan_id,
                    start_time=start_time,
                    end_time=end_time,
                    pest=pest,
                    pick=pick,
                    mark=mark
                )
        return Response({"code": 0, "msg": "success"})


class MongoPlantInfoDeleteAPIView(APIView):

    def post(self, request):
        # 作物删除
        request_data = request.data
        plan_id = request_data.get("plan_id")
        # 查看此作物有没有被种植
        land_plan = LandPlanInfo.objects.filter(plan_id=plan_id)
        for k in land_plan:
            print(k.id)
        if land_plan:
            return Response({"code": 2, "msg": "此作物已种植，不能被删除"})
        else:
            try:
                MongoPlantInfo.objects.filter(id=plan_id).update(is_delete=0)
                PlanWeekend.objects.filter(plan_id=plan_id).update(is_delete=0)
                return Response({"code": 0, "msg": "作物删除成功"})
            except Exception as e:
                return Response({"code": 0, "msg": "作物删除失败"})


class MongoGrowOperateAPIView(APIView):

    def post(self, request):
        # 种植新增
        request_data = request.data 
        try:
            pl_id = request_data.get("pl_id")
            plan_id = request_data.get("plan_id")
            plan_time = request_data.get("plan_time")
            LandPlanInfo.objects.filter(id=pl_id).update(
                plan_id=plan_id,
                plan_time=plan_time,
                status="采收"
            )
            return Response({"code": 0, "msg": "地块操作成功"})
        except Exception as e:
            return Response({"code": 2, "msg": "请检查参数"})


class MongoGrowOperateRecoveryAPIView(APIView):

    def post(self, request):
        # 种植采收
        request_data = request.data 
        try:
            pl_id = request_data.get("pl_id")
            recovery_time = request_data.get("recovery_time")
            recovery_kg = request_data.get("recovery_kg")
            land_plan = LandPlanInfo.objects.filter(id=pl_id, status="采收").order_by("-addtime").first()
            land_plan.recovery_kg = recovery_kg
            land_plan.recovery_time = recovery_time
            land_plan.save()
            LandPlanInfo.objects.create(
                land_id=land_plan.land_id,
                addtime=int(time.time()),
                status="种植"
            )
            return Response({"code": 0, "msg": "地块操作成功"})
        except Exception as e:
            return Response({"code": 2, "msg": "请检查参数"})
    

class PlanWeekendAPIView(APIView):

    def post(self, request):
        # 生成周期列表
        queryset = PlanWeekend.objects.filter(is_delete=1)
        serializers = PlanWeekendSerializers(queryset, many=True)
        return Response({"code": 0, "msg": "success", "data": serializers.data})
    

class PlanWeekendDelete(APIView):

    def post(self, request):
        request_data = request.data
        try: 
            PlanWeekend.objects.filter(id=request_data.get("id")).update(is_delete=0)
            return Response({"code": 0, "msg": "删除成功"})
        except Exception as e:
            return Response({"code": 2, "msg": "删除失败"})
        

class PlanWeekendAddAPIView(APIView):

    def post(self, request):
        request_data = request.data
        try:
            PlanWeekend.objects.create(
                plan_id=request_data.get("plan_id"),
                name=request_data.get("name"),
                start_time=request_data.get("start_time"),
                end_time=request_data.get("end_time"),
                pest=request_data.get("pest"),
                pick=request_data.get("pick"),
                mark=request_data.get("mark")
            )
            return Response({"code": 0, "msg": "success"})
        except Exception as e:
            return Response({"code": 2, "msg": "添加失败"})


class CountryModelAPIView(APIView):

    def post(self, request):
        # 乡村列表
        request_data = request.data 
        page_num = int(request_data.get("pagenum")) if request_data.get("pagenum") else 1
        page_size = int(request_data.get("pagesize")) if request_data.get("pagesize") else 10
        title = request_data.get("title")
        if title:
            queryset = CountryModel.objects.filter(is_delete=1, title__icontains=title).order_by("-uptime")
        else:
            queryset = CountryModel.objects.filter(is_delete=1).order_by("-uptime")
        total_obj = queryset.count()
        paginator = Paginator(queryset, page_size)
        page_obj = paginator.get_page(page_num)
        serializers = CountryModelSerializers(page_obj, many=True)
        return Response({"code": 0, "msg": "success", "data": serializers.data, "count": total_obj})


class CountryModelAddAPIView(APIView):

    def post(self, request):
        # 乡村增加
        request_data = request.data
        CountryModel.objects.create(
            title=request_data.get("title"),
            cover_img=request_data.get("cover_img"),
            introduce=request_data.get("introduce"),
            content=request_data.get("content"),
            uptime=int(time.time())
        )
        return Response({"code": 0, "msg": "success"})
    
class CountryModelUpdateAPIView(APIView):

    def post(self, request):
        # 乡村增加
        request_data = request.data
        CountryModel.objects.filter(id=request_data.get("country_id")).update(
            title=request_data.get("title"),
            cover_img=request_data.get("cover_img"),
            introduce=request_data.get("introduce"),
            content=request_data.get("content")
        )
        return Response({"code": 0, "msg": "success"})
    

class CountryModelDeleteAPIView(APIView):

    def post(self, request):
        # 乡村删除
        request_data = request.data
        try:
            CountryModel.objects.filter(id=request_data.get("country_id")).update(is_delete=0)
            return Response({"code": 0, "msg": "删除成功"})
        except Exception as e:
            return Response({"code": 2, "msg": "删除失败"})


class LandPlanInfoAPIView(APIView):

    def post(self, request):
        # 种植采收列表及统计信息
        request_data = request.data 
        plan = request_data.get("plan")
        year = int(request_data.get("year"))
        page_num = int(request_data.get("pagenum")) if request_data.get("pagenum") else 1
        page_size = int(request_data.get("pagesize")) if request_data.get("pagesize") else 10
        start_timestamp = datetime.datetime(year, 1,1,0,0).timestamp()
        end_timestatmp = datetime.datetime(year, 12,31,23,59).timestamp()
        plan_ids = []
        if plan:
            plan_ids = MongoPlantInfo.objects.filter(plantname__icontains=plan).values_list("id", flat=True)
        if plan_ids and year:
            queryset = LandPlanInfo.objects.filter(Q(plan_id__in = plan_ids) & Q(addtime__gte=start_timestamp, addtime__lte=end_timestatmp)).filter(is_delete=1).order_by("-addtime")
        elif year:
            queryset = LandPlanInfo.objects.filter(addtime__gte=start_timestamp, addtime__lte=end_timestatmp).filter(is_delete=1).order_by("-addtime")
        elif plan_ids:
            queryset = LandPlanInfo.objects.filter(plan_id__in = plan_ids).filter(is_delete=1).order_by("-addtime")
        total_obj = queryset.count()
        paginator = Paginator(queryset, page_size)
        page_obj = paginator.get_page(page_num)
        serializers = LandPlanInfoSerializers(page_obj, many=True)
        # 折线图
        year_value = LandPlanInfo.objects.all().values_list("addtime", flat=True).order_by("-addtime")
        years = []
        for year in year_value:
            y = datetime.datetime.fromtimestamp(year).year
            if y not in years:
                years.append(y)
        years = years[:5]
        # 获取最近5年的作物ID
        plan_ids = LandPlanInfo.objects.filter(addtime__gte=start_timestamp, addtime__lte=end_timestatmp).distinct().values_list("plan_id", flat=True).order_by("plan_id")
        counts = []
        for i in years:
            start_timestamp = datetime.datetime(i, 1,1,0,0).timestamp()
            end_timestatmp = datetime.datetime(i, 12,31,23,59).timestamp()
            plan_totals = LandPlanInfo.objects.filter(addtime__gte=start_timestamp, addtime__lte=end_timestatmp).values("plan_id").annotate(total=Count("plan_id")).order_by("plan_id").values_list("plan_id", "total")
            inners = {}
            for k in plan_totals:
                inners[str(k[0])] = k[1]
            pid =[]
            for id in plan_ids:
                pid.append(inners.get(str(id), 0))
            counts.append(pid)
        plannames = []
        for p in plan_ids:
            plan = MongoPlantInfo.objects.filter(id=p)
            if plan:
                planname = plan.first().plantname + plan.first().planttype
            else:
                planname = ""
            plannames.append(planname)
        return Response({
            "code": 0, 
            "msg": "success", 
            "data": serializers.data, 
            "count": total_obj, 
            "charts": {
                "years": years,
                "data": counts,
                "plan": plannames
            }
        })


