import time
from datetime import datetime

import boto3
import botocore
from django.core.paginator import Paginator
from django.views import View
from obs import ObsClient
from Ansjer.config import HUAWEICLOUD_AK, HUAWEICLOUD_SK, HUAWEICLOUD_OBS_SERVER, CONFIG_INFO, CONFIG_CN, CONFIG_TEST, \
    AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY

from Roomumy.models import TimeAlbum, AlbumMedia, TimeDiary, DiaryAlbumMediaRelation
from Service.CommonService import CommonService


class TimeAlbumView(View):
    def get(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        operation = kwargs.get('operation')
        return self.validation(request.GET, request, operation)

    def post(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        operation = kwargs.get('operation')
        return self.validation(request.POST, request, operation)

    def validation(self, request_dict, request, operation):
        token_code, user_id, response = CommonService.verify_token_get_user_id(request_dict, request)
        if operation == 'clearAlbumMedia':  # 删除相册媒体
            return self.clear_album_media(response)
        else:
            if token_code != 0:
                return response.json(token_code)
            if operation == 'getAlbumPic':  # 查询相册列表
                return self.get_album_pic(user_id, request_dict, response)
            elif operation == 'getTimeDiary':  # 获取时光日记列表
                return self.get_time_diary(user_id, request_dict, response)
            elif operation == 'picLiked':  # 喜欢图片
                return self.pic_liked(user_id, request_dict, response)
            else:
                return response.json(414)

    def get_album_pic(self, user_id, request_dict, response):
        device_id = request_dict.get('deviceId', None)
        start_time = request_dict.get('startTime', None)
        end_time = request_dict.get('endTime', None)
        page = request_dict.get('page', 1)  # 当前页码，默认为1
        page_size = request_dict.get('pageSize', 10)  # 每页显示的记录数，默认为10

        # 检查是否提供了uid，如果没有提供返回错误
        if device_id is None:
            return response.json(444)
        try:
            # 查询TimeAlbum表，按uid过滤，且如果提供了album_date，则进一步按album_date过滤
            time_album_qs = TimeAlbum.objects.filter(device_id=device_id).order_by('-album_date')

            if start_time and end_time:
                time_album_qs = time_album_qs.filter(album_date__gte=start_time, album_date__lte=end_time)

            # 如果没有找到符合条件的TimeAlbum记录，返回错误
            if not time_album_qs.exists():
                return response.json(0, {})

            # 对TimeAlbum结果进行分页
            paginator = Paginator(time_album_qs, page_size)
            time_albums = paginator.page(page)  # 获取当前页的数据

            time_album_list = []
            # 对每个TimeAlbum，查询相关的AlbumMedia
            for time_album in time_albums:
                # 查询与当前time_album_id关联的AlbumMedia记录
                time_album_info = []
                album_media_qs = AlbumMedia.objects.filter(time_album_id=time_album.id).values('id', 'device_id', 'channel',
                                                                                               'event_time', 'status',
                                                                                               'storage_location')

                if album_media_qs.exists():
                    for album_media in album_media_qs:
                        storage_location = album_media['storage_location']
                        uid = album_media['device_id']
                        channel = album_media['channel']
                        event_time = album_media['event_time']
                        image = self.media_url(storage_location, uid, channel, event_time)

                        # 判断是否加入时光日记
                        liked_status = 0
                        if DiaryAlbumMediaRelation.objects.filter(
                                album_media_id=album_media['id'],
                                diary__user_id=user_id
                        ).exists():
                            liked_status = 1
                        time_album_info.append({
                            'picId': album_media['id'],
                            'image': image,
                            'likedStatus': liked_status,
                        })
                    time_album_list.append({
                        'albumDate': time_album.album_date,
                        'albumTitle': time_album.album_title,
                        'info': time_album_info
                    })

            # 返回分页结果和数据
            return response.json(0, {
                'data': time_album_list,
                'total': paginator.count,  # 总记录数
            })
        except Exception as e:
            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

    def get_time_diary(self, user_id, request_dict, response):
        start_time = request_dict.get('startTime', None)
        end_time = request_dict.get('endTime', None)
        page = int(request_dict.get('page', 1))
        page_size = int(request_dict.get('pageSize', 10))

        try:
            # 基础查询
            time_diary_qs = TimeDiary.objects.filter(user_id=user_id).order_by('-diary_date')

            # 时间范围过滤
            if start_time and end_time:
                time_diary_qs = time_diary_qs.filter(diary_date__gte=start_time, diary_date__lte=end_time)

            # 分页
            paginator = Paginator(time_diary_qs, page_size)
            diaries_page = paginator.get_page(page)

            diary_data_list = []
            for diary in diaries_page:
                # 通过中间表获取关联的图片
                relations = DiaryAlbumMediaRelation.objects.filter(diary=diary).select_related('album_media')

                media_list = []
                for relation in relations:
                    media = relation.album_media
                    media_list.append({
                        'picId': media.id,
                        'likeStatus': 1,
                        'image': self.media_url(media.storage_location, media.device_id, media.channel,
                                                    media.event_time)
                    })

                diary_data_list.append({
                    'diary_date': diary.diary_date,
                    'info': media_list
                })

            return response.json(0, {
                'data': diary_data_list,
                'total': paginator.count,
            })

        except Exception as e:
            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

    @staticmethod
    def pic_liked(user_id, request_dict, response):
        pic_id = request_dict.get('picId', None)
        liked_status = request_dict.get('likedStatus', None)

        if not all([pic_id, liked_status]):
            return response.json(444)

        liked_status = int(liked_status)

        try:
            album_media = AlbumMedia.objects.filter(id=pic_id).first()
            if not album_media:
                return response.json(404, 'pic not found')

            # 获取相册的日期
            time_diary_qs = AlbumMedia.objects.filter(id=pic_id).values('time_album_id', 'event_time', 'status')
            if not time_diary_qs.exists():
                return response.json(173)

            event_time = time_diary_qs[0]['event_time']
            dt = datetime.fromtimestamp(event_time)
            dt_zero = datetime(dt.year, dt.month, dt.day)

            diary_date = int(dt_zero.timestamp())

            # 查找或创建用户今天的 TimeDiary
            time_diary, created = TimeDiary.objects.get_or_create(
                user_id=user_id,
                diary_date=diary_date,
                defaults={
                    'created_time': int(time.time()),
                    'updated_time': int(time.time())
                }
            )

            if liked_status == 1:
                # 添加到 TimeDiary（中间表中插入）
                DiaryAlbumMediaRelation.objects.get_or_create(
                    diary=time_diary,
                    album_media=album_media,
                    defaults={
                        'created_time': int(time.time()),
                        'updated_time': int(time.time())
                    }
                )
                time_diary_qs.update(status=2, updated_time=int(time.time()))

            elif liked_status == 0:
                # 从中间表移除
                DiaryAlbumMediaRelation.objects.filter(diary=time_diary, album_media=album_media).delete()
                if DiaryAlbumMediaRelation.objects.filter(diary=time_diary).count() == 0:
                    time_diary.delete()
                if not DiaryAlbumMediaRelation.objects.filter(album_media=album_media).exists():
                    time_diary_qs.update(status=1, updated_time=int(time.time()))

            return response.json(0)

        except Exception as e:
            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))

    @staticmethod
    def media_url(storage_location, uid, channel, event_time):
        if storage_location == 2:
            obj_name = f'roomumy/albumMedia/{uid}/{channel}/{event_time}.jpeg'
            if CONFIG_INFO == CONFIG_CN or CONFIG_INFO == CONFIG_TEST:
                aws_client = boto3.client(
                    's3',
                    aws_access_key_id=AWS_ACCESS_KEY_ID[0],
                    aws_secret_access_key=AWS_SECRET_ACCESS_KEY[0],
                    region_name='cn-northwest-1'
                )
            else:
                aws_client = boto3.client(
                    's3',
                    aws_access_key_id=AWS_ACCESS_KEY_ID[1],
                    aws_secret_access_key=AWS_SECRET_ACCESS_KEY[1],
                    region_name='cn-northwest-1'
                )
            params = {'Key': obj_name, 'Bucket': 'ansjerfilemanager'}
            media_url = aws_client.generate_presigned_url(
                'get_object', Params=params, ExpiresIn=300)
        elif storage_location == 5:
            obj_name = f'roomumy/albumMedia/{uid}/{channel}/{event_time}.jpeg'
            obs_client = ObsClient(
                access_key_id=HUAWEICLOUD_AK, secret_access_key=HUAWEICLOUD_SK, server=HUAWEICLOUD_OBS_SERVER)
            create_res = obs_client.createSignedUrl(
                method='GET', bucketName="asj-app", objectKey=obj_name, expires=600)
            media_url = create_res.signedUrl
        else:
            media_url = ''
        return media_url


    @staticmethod
    def clear_album_media(response):
        # 获取当前时间
        current_time = int(time.time()) - 2592000

        # 预加载关联的TimeAlbum对象
        album_media_qs = AlbumMedia.objects.filter(
            status=1,
            event_time__lt=current_time
        )

        # 如果没有需要处理的数据，直接返回
        if not album_media_qs.exists():
            return response.json(0)

        # 初始化 Huawei Cloud 的 ObsClient
        obs_client = ObsClient(
            access_key_id=HUAWEICLOUD_AK,
            secret_access_key=HUAWEICLOUD_SK,
            server=HUAWEICLOUD_OBS_SERVER
        )

        # 根据配置选择初始化 AWS 客户端
        aws_client_config = {
            'aws_access_key_id': AWS_ACCESS_KEY_ID[0] if CONFIG_INFO in [CONFIG_CN, CONFIG_TEST] else AWS_ACCESS_KEY_ID[1],
            'aws_secret_access_key': AWS_SECRET_ACCESS_KEY[0] if CONFIG_INFO in [CONFIG_CN, CONFIG_TEST] else AWS_SECRET_ACCESS_KEY[1],
            'region_name': 'cn-northwest-1' if CONFIG_INFO in [CONFIG_CN, CONFIG_TEST] else 'us-east-1'
        }
        aws_client = boto3.client('s3', **aws_client_config)

        # 准备批量删除的对象
        aws_objects_to_delete = []
        obs_objects_to_delete = []
        time_album_ids_to_check = set()
        album_media_ids_to_delete = []

        # 收集需要删除的对象和时间相册ID
        for album_media in album_media_qs:
            uid = album_media.device_id
            event_time = album_media.event_time
            obj_name = f'roomumy/albumMedia/{uid}/{album_media.channel}/{event_time}.jpeg'

            album_media_ids_to_delete.append(album_media.id)

            if album_media.time_album_id:
                time_album_ids_to_check.add(album_media.time_album_id)

            if album_media.storage_location == 2:
                aws_objects_to_delete.append({'Key': obj_name})
            elif album_media.storage_location == 5:
                obs_objects_to_delete.append(obj_name)

        # 批量删除AWS对象
        if aws_objects_to_delete:
            # AWS S3支持批量删除，最多1000个对象每次
            for i in range(0, len(aws_objects_to_delete), 1000):
                batch = aws_objects_to_delete[i:i + 1000]
                aws_client.delete_objects(
                    Bucket='ansjerfilemanager',
                    Delete={'Objects': batch}
                )

        # 删除华为OBS对象
        if obs_objects_to_delete:
            for obj_name in obs_objects_to_delete:
                obs_client.deleteObject(bucketName="asj-app", objectKey=obj_name)

        # 检查需要删除的TimeAlbum
        if time_album_ids_to_check:
            # 查询TimeAlbum关联的AlbumMedia
            time_albums_with_media = AlbumMedia.objects.filter(
                time_album_id__in=time_album_ids_to_check
            ).exclude(
                id__in=album_media_ids_to_delete
            ).values_list('time_album_id', flat=True).distinct()

            # 找出没有关联媒体的TimeAlbum
            time_albums_to_delete = set(time_album_ids_to_check) - set(time_albums_with_media)

            # 批量删除TimeAlbum
            if time_albums_to_delete:
                TimeAlbum.objects.filter(id__in=time_albums_to_delete).delete()

        # 处理完所有项后，删除数据库中的记录
        album_media_qs.delete()

        return response.json(0)