#!/usr/bin/env python3
import argparse, os, sys
from telethon import TelegramClient
from telethon.errors import RPCError
from telethon.tl.types import User, Chat, Channel

try:
    from dotenv import load_dotenv
    load_dotenv()
except Exception:
    pass

def env(name, default=None, cast=str):
    v = os.getenv(name, default)
    if v is None:
        return None
    return cast(v) if cast and v is not None else v

def print_dialog_row(d, out=sys.stdout):
    ent = d.entity
    if isinstance(ent, User):
        typ = "user"
        uname = getattr(ent, "username", None)
        forum = "-"
    elif isinstance(ent, Chat):
        typ = "group"
        uname = getattr(ent, "username", None)
        forum = "no"
    elif isinstance(ent, Channel):
        typ = "channel" if ent.broadcast else ("supergroup" if ent.megagroup else "channel")
        uname = getattr(ent, "username", None)
        forum = "yes" if getattr(ent, "forum", False) else "no"
    else:
        typ = "unknown"
        uname = None
        forum = "-"
    name = d.name or ""
    uid = d.id  # numeric id (users positive, groups/channels usually negative: -100…)
    uname = uname or ""
    print(f"{uid}\t{typ}\t{forum}\t{name}\t{uname}", file=out)

def main():
    parser = argparse.ArgumentParser(
        description="Post to Telegram as your personal account (channel, group, user, or forum topic)."
    )

    # List/search mode (no target required)
    parser.add_argument("--list", action="store_true", help="List your dialogs (DMs, groups, channels) and exit.")
    parser.add_argument("--find", help="Filter list by case-insensitive substring (in name or username).")

    # Normal send options
    parser.add_argument("--to", help="Target: @channelusername, numeric chat ID (-100...), phone/username.")
    parser.add_argument("--text", help="Text to send.")
    parser.add_argument("--html", action="store_true", help="Parse text as HTML.")
    parser.add_argument("--md", action="store_true", help="Parse text as Markdown.")
    parser.add_argument("--no-preview", action="store_true", help="Disable link previews for text.")
    parser.add_argument("--photo", help="Path to an image.")
    parser.add_argument("--video", help="Path to a video.")
    parser.add_argument("--file", help="Path to any file/document.")
    parser.add_argument("--caption", help="Caption for photo/video/file.")
    parser.add_argument("--reply", type=int, help="Reply to this message ID.")
    parser.add_argument("--topic-id", type=int, help="Forum topic ID (root message ID) in a forum-enabled supergroup.")
    parser.add_argument("--pin", action="store_true", help="Pin the message after sending (requires admin rights).")
    parser.add_argument("--silent", action="store_true", help="Send silently (no sound).")
    parser.add_argument("--session", default=env("SESSION","tg_session"), help="Session file name.")
    parser.add_argument("--api-id", type=int, default=env("API_ID", None, int), help="Telegram API ID.")
    parser.add_argument("--api-hash", default=env("API_HASH"), help="Telegram API hash.")
    parser.add_argument("--phone", default=env("PHONE_NUMBER"), help="Your phone number for login (E.164).")

    args = parser.parse_args()

    if not args.api_id or not args.api_hash:
        print("ERROR: API_ID/API_HASH missing. Use --api-id/--api-hash or set in .env", file=sys.stderr)
        sys.exit(1)

    # If both --reply and --topic-id are provided, prefer --reply
    effective_reply = args.reply if args.reply else args.topic_id

    client = TelegramClient(args.session, args.api_id, args.api_hash)

    async def run():
        # Login (first run will prompt)
        if not await client.is_user_authorized():
            if not args.phone:
                print("First login requires --phone or PHONE_NUMBER in .env", file=sys.stderr)
                sys.exit(1)
            await client.send_code_request(args.phone)
            code = input("Enter the login code you received in Telegram: ").strip()
            try:
                await client.sign_in(args.phone, code)
            except RPCError as e:
                print(f"Login failed: {e}", file=sys.stderr)
                sys.exit(1)

        # LIST MODE
        if args.list:
            # Header
            print("id\ttype\tforum\tname\tusername")
            async for d in client.iter_dialogs():
                if args.find:
                    q = args.find.lower()
                    nm = (d.name or "").lower()
                    un = (getattr(d.entity, "username", "") or "").lower()
                    if q not in nm and q not in un:
                        continue
                print_dialog_row(d)
            return

        # SEND MODE requires --to
        if not args.to:
            print("ERROR: --to is required (or use --list to enumerate chats).", file=sys.stderr)
            sys.exit(1)

        # Resolve target entity
        try:
            target = await client.get_entity(args.to)
        except Exception as e:
            print(f"Could not resolve target '{args.to}': {e}", file=sys.stderr)
            sys.exit(1)

        # Choose parse mode
        parse_mode = None
        if args.html and args.md:
            print("Choose only one of --html or --md.", file=sys.stderr)
            sys.exit(1)
        if args.html:
            parse_mode = "html"
        elif args.md:
            parse_mode = "md"

        msg = None
        try:
            if args.photo:
                msg = await client.send_file(
                    target,
                    args.photo,
                    caption=args.caption,
                    reply_to=effective_reply,
                    silent=args.silent,
                    supports_streaming=False
                )
            elif args.video:
                msg = await client.send_file(
                    target,
                    args.video,
                    caption=args.caption,
                    reply_to=effective_reply,
                    silent=args.silent,
                    supports_streaming=True
                )
            elif args.file:
                msg = await client.send_file(
                    target,
                    args.file,
                    caption=args.caption,
                    reply_to=effective_reply,
                    silent=args.silent
                )
            elif args.text:
                msg = await client.send_message(
                    target,
                    args.text,
                    parse_mode=parse_mode,
                    link_preview=not args.no_preview,
                    reply_to=effective_reply,
                    silent=args.silent
                )
            else:
                print("Nothing to send. Provide --text or --photo/--video/--file.", file=sys.stderr)
                sys.exit(1)

            print(f"Sent message id={msg.id} to {args.to}")

            if args.pin:
                try:
                    await client.pin_message(target, msg, notify=not args.silent)
                    print("Pinned message.")
                except RPCError as e:
                    print(f"Pin failed (need admin rights?): {e}", file=sys.stderr)

        except RPCError as e:
            print(f"Send failed: {e}", file=sys.stderr)
            sys.exit(1)

    with client:
        client.loop.run_until_complete(run())

if __name__ == "__main__":
    main()
