import json
import logging

import redis
import scrapy
from telethon.errors import SessionPasswordNeededError
from telethon.sync import TelegramClient
from telethon.tl.functions.messages import GetDialogsRequest
from telethon.tl.types import InputPeerEmpty

from MediaSpiders.items import TelegramGroup, TelegramMessage, TelegramMember
from MediaSpiders.utils.image_utils import bytes_image_to_base64
from MediaSpiders.utils.string_utils import get_str_md5
from MediaSpiders.utils.time_utils import transfer_datetime


class TelegramSpider(scrapy.Spider):
    name = 'TelegramSpider'
    custom_settings = {
        'ITEM_PIPELINES': {
            'MediaSpiders.pipelines.TelegramDataSaveToMySQL': 300
        },
        'SPIDER_MIDDLEWARES': {},
        'DOWNLOADER_MIDDLEWARES': {}
    }

    def __init__(self, params=None, **kwargs):
        super().__init__(**kwargs)
        json_params = json.loads(params)
        self.job_id = ''
        self.proxy = None
        self.api_id = 24689072
        self.api_hash = '2b67cbf4ba66ed591ec484df85c91f57'
        self.phone = '+27748684730'
        self.telegram_client = None
        self.redis_client = None
        self.use_group_white_list = False
        self.group_white_list = []
        if 'job_id' in json_params:
            self.job_id = json_params['job_id']
        if 'proxy' in json_params:
            self.proxy = ("socks5", '127.0.0.1', 10808)

    def start_requests(self):
        if self.proxy:
            self.telegram_client = TelegramClient(self.phone, self.api_id, self.api_hash, timeout=10, proxy=self.proxy)
        else:
            self.telegram_client = TelegramClient(self.phone, self.api_id, self.api_hash, timeout=10)
        self.telegram_client.connect()
        self.redis_client = redis.Redis(host=self.settings['REDIS_HOST'], port=self.settings['REDIS_PORT'],
                                        password=self.settings['REDIS_PWD'])
        for white_list_item in self.redis_client.smembers('MediaSpiders:Telegram_white_list'):
            self.group_white_list.append(white_list_item.decode())
        if not self.telegram_client.is_user_authorized():
            self.telegram_client.send_code_request(self.phone)
            try:
                self.telegram_client.sign_in(self.phone, input('Enter the code:'))
            except SessionPasswordNeededError:
                self.telegram_client.sign_in(password='1234qwer%')
        yield scrapy.Request('https://www.baidu.com/', callback=self.parse)

    def parse(self, response):
        chats = []
        last_date = None
        chunk_size = 200
        groups = []
        channels = []

        result = self.telegram_client(GetDialogsRequest(
            offset_date=last_date,
            offset_id=0,
            offset_peer=InputPeerEmpty(),
            limit=chunk_size,
            hash=0
        ))

        chats.extend(result.chats)
        logging.info(chats)

        # 从拿到的聊天列表中获取聊天群组信息和组成员信息
        for chat in chats:
            # 只获取在白名单中的群组和频道
            if chat.title not in self.group_white_list:
                if self.use_group_white_list:
                    continue
            try:
                group_item = TelegramGroup()
                group_item['id'] = chat.id
                group_item['name'] = chat.title
                group_item['link'] = chat.username
                group_item['number_of_members'] = chat.participants_count
                group_item['description'] = ''
                members_id = []
                if chat.megagroup:
                    group_item['type'] = 'o'
                    groups.append(chat)
                    # participants = self.telegram_client.get_participants(chat, aggressive=True)
                    # for p in participants:
                    #     member_item = TelegramMember()
                    #     try:
                    #         members_id.append(p.id)
                    #         member_item['id'] = p.id
                    #         member_item['name'] = p.username
                    #         member_item['alias'] = p.first_name
                    #         member_item['role'] = 'u'
                    #         if p.photo:
                    #             member_photo_bytes = self.telegram_client.download_profile_photo(p, file=bytes)
                    #             member_photo_base64 = bytes_image_to_base64(member_photo_bytes)
                    #             member_item['profile_photo'] = member_photo_base64
                    #         if p.phone:
                    #             member_item['mobile'] = p.phone
                    #         if p.participant.admin_rights.add_admins:
                    #             member_item['role'] = 'a'
                    #     except Exception as e:
                    #         logging.debug(repr(e))
                    #     yield member_item
                if chat.broadcast:
                    group_item['type'] = 'c'
                    channels.append(chat)
                group_item['members_id'] = json.dumps(members_id)
                if chat.photo:
                    chat_photo_bytes = self.telegram_client.download_profile_photo(chat, file=bytes)
                    chat_photo_base64 = bytes_image_to_base64(chat_photo_bytes)
                    group_item['profile_photo'] = chat_photo_base64
                yield group_item
            except Exception as e:
                logging.debug(repr(e))
                continue

        # 获取频道中的消息
        for c in channels:
            entity = self.telegram_client.get_entity(c.id)
            # 获取频道中的消息
            channel_messages = self.telegram_client.iter_messages(entity, limit=100)
            for c_message in channel_messages:
                try:
                    c_message_item = TelegramMessage()
                    c_message_item['sender'] = json.dumps({
                        'id': c_message.sender.id,
                        'username': c_message.sender.username,
                        'alias': c_message.sender.title
                    }, ensure_ascii=False)
                    c_message_item['send_time'] = transfer_datetime(c_message.date)
                    c_message_item['receiver'] = json.dumps({
                        'id': c_message.chat.id,
                        'username': c_message.chat.username,
                        'alias': c_message.chat.title,
                        'type': ['c', 'o'][c_message.chat.megagroup]
                    }, ensure_ascii=False)
                    c_message_item['text'] = ''
                    if c_message.message:
                        c_message_item['text'] = c_message.message
                    c_message_item['files'] = ''
                    c_message_item['links'] = ''
                    c_message_item['id'] = get_str_md5(
                        c_message_item['sender'] + c_message_item['send_time'] + c_message_item['text'])
                    yield c_message_item
                except Exception as e:
                    logging.error(repr(e))

        # 获取群组中的消息
        for g in groups:
            # 获取指定群组的信息
            entity = self.telegram_client.get_entity(g.id)
            group_messages = self.telegram_client.get_messages(entity, limit=100)
            for g_message in group_messages:
                try:
                    g_message_item = TelegramMessage()
                    g_message_item['sender'] = json.dumps({
                        'id': g_message.sender.id,
                        'username': g_message.sender.username,
                        'alias': g_message.sender.first_name
                    }, ensure_ascii=False)
                    g_message_item['send_time'] = transfer_datetime(g_message.date)
                    g_message_item['receiver'] = json.dumps({
                        'id': g_message.chat.id,
                        'username': g_message.chat.username,
                        'alias': g_message.chat.title,
                        'type': ['c', 'o'][g_message.chat.megagroup]
                    }, ensure_ascii=False)
                    g_message_item['text'] = ''
                    if g_message.text:
                        g_message_item['text'] = g_message.text
                    g_message_item['files'] = ''
                    g_message_item['links'] = ''
                    g_message_item['id'] = get_str_md5(
                        g_message_item['sender'] + g_message_item['send_time'] + g_message_item['text'])
                    yield g_message_item
                except Exception as e:
                    logging.error(repr(e))
