import { ArgumentError, CommandExecutionError } from '@jackwener/opencli/errors';
import { cli, Strategy } from '@jackwener/opencli/registry';
const INSTAGRAM_INBOX_URL = 'https://www.instagram.com/direct/inbox/';
const INSTAGRAM_NOTE_DOC_ID = '25155183657506484';
const INSTAGRAM_NOTE_MUTATION_NAME = 'usePolarisCreateInboxTrayItemSubmitMutation';
const INSTAGRAM_NOTE_ROOT_FIELD = 'xdt_create_inbox_tray_item';
function requirePage(page) {
    if (!page)
        throw new CommandExecutionError('Browser session required for instagram note');
    return page;
}
function validateInstagramNoteArgs(kwargs) {
    if (kwargs.content === undefined) {
        throw new ArgumentError('Argument "content" is required.', 'Provide a note text, for example: opencli instagram note "hello"');
    }
}
function normalizeInstagramNoteContent(kwargs) {
    const content = String(kwargs.content ?? '').trim();
    if (!content) {
        throw new ArgumentError('Instagram note content cannot be empty.', 'Provide a non-empty note text, for example: opencli instagram note "hello"');
    }
    if (Array.from(content).length > 60) {
        throw new ArgumentError('Instagram note content must be 60 characters or fewer.', 'Shorten the note text and try again.');
    }
    return content;
}
function buildNoteSuccessResult(noteId) {
    return [{
            status: '✅ Posted',
            detail: 'Instagram note published successfully',
            noteId,
        }];
}
function buildPublishInstagramNoteJs(content) {
    return `
    (async () => {
      const input = ${JSON.stringify({ content })};
      const html = document.documentElement?.outerHTML || '';
      const scripts = Array.from(document.scripts || [])
        .map((script) => script.textContent || '')
        .join('\\n');
      const source = html + '\\n' + scripts;
      const pick = (patterns) => {
        for (const pattern of patterns) {
          const match = source.match(pattern);
          if (!match) continue;
          for (let index = 1; index < match.length; index += 1) {
            if (match[index]) return match[index];
          }
          return match[0] || '';
        }
        return '';
      };
      const readCookie = (name) => {
        const prefix = name + '=';
        const part = document.cookie
          .split('; ')
          .find((cookie) => cookie.startsWith(prefix));
        return part ? decodeURIComponent(part.slice(prefix.length)) : '';
      };
      const actorId = pick([
        /"actorID":"(\\d+)"/,
        /"actor_id":"(\\d+)"/,
        /"viewerId":"(\\d+)"/,
      ]);
      const fbDtsg = pick([
        /(NAF[a-zA-Z0-9:_-]{20,})/,
        /(NAf[a-zA-Z0-9:_-]{20,})/,
      ]);
      const lsd = pick([
        /"LSD",\\[\\],\\{"token":"([^"]+)"\\}/,
        /"lsd":"([^"]+)"/,
      ]);
      const appId = pick([
        /"X-IG-App-ID":"(\\d+)"/,
        /"instagramWebAppId":"(\\d+)"/,
        /"appId":"(\\d+)"/,
      ]);
      const asbdId = pick([
        /"X-ASBD-ID":"(\\d+)"/,
        /"asbd_id":"(\\d+)"/,
      ]);
      const spinR = pick([/"__spin_r":(\\d+)/]);
      const spinB = pick([/"__spin_b":"([^"]+)"/]);
      const spinT = pick([/"__spin_t":(\\d+)/]);
      const csrfToken = readCookie('csrftoken') || pick([
        /"csrf_token":"([^"]+)"/,
        /"csrfToken":"([^"]+)"/,
      ]);
      const jazoest = fbDtsg
        ? '2' + Array.from(fbDtsg).reduce((total, char) => total + char.charCodeAt(0), 0)
        : '';

      if (!actorId || !fbDtsg || !lsd || !appId || !csrfToken || !spinR || !spinB || !spinT || !jazoest) {
        return {
          ok: false,
          stage: 'config',
          text: JSON.stringify({
            actorId: Boolean(actorId),
            fbDtsg: Boolean(fbDtsg),
            lsd: Boolean(lsd),
            appId: Boolean(appId),
            csrfToken: Boolean(csrfToken),
            spinR: Boolean(spinR),
            spinB: Boolean(spinB),
            spinT: Boolean(spinT),
            jazoest: Boolean(jazoest),
          }),
        };
      }

      const variables = {
        input: {
          actor_id: actorId,
          client_mutation_id: '1',
          additional_params: {
            note_create_params: {
              note_style: 0,
              text: input.content,
            },
          },
          audience: 0,
          inbox_tray_item_type: 'note',
        },
      };

      const body = new URLSearchParams();
      body.set('av', actorId);
      body.set('__user', '0');
      body.set('__a', '1');
      body.set('__req', '1');
      body.set('__hs', '');
      body.set('dpr', String(window.devicePixelRatio || 1));
      body.set('__ccg', 'UNKNOWN');
      body.set('__rev', spinR);
      body.set('__s', '');
      body.set('__hsi', '');
      body.set('__dyn', '');
      body.set('__csr', '');
      body.set('__comet_req', '7');
      body.set('fb_dtsg', fbDtsg);
      body.set('jazoest', jazoest);
      body.set('lsd', lsd);
      body.set('__spin_r', spinR);
      body.set('__spin_b', spinB);
      body.set('__spin_t', spinT);
      body.set('fb_api_caller_class', 'RelayModern');
      body.set('fb_api_req_friendly_name', ${JSON.stringify(INSTAGRAM_NOTE_MUTATION_NAME)});
      body.set('variables', JSON.stringify(variables));
      body.set('server_timestamps', 'true');
      body.set('doc_id', ${JSON.stringify(INSTAGRAM_NOTE_DOC_ID)});

      const headers = {
        Accept: '*/*',
        'Content-Type': 'application/x-www-form-urlencoded',
        'X-ASBD-ID': asbdId || undefined,
        'X-CSRFToken': csrfToken,
        'X-FB-Friendly-Name': ${JSON.stringify(INSTAGRAM_NOTE_MUTATION_NAME)},
        'X-FB-LSD': lsd,
        'X-IG-App-ID': appId,
        'X-Root-Field-Name': ${JSON.stringify(INSTAGRAM_NOTE_ROOT_FIELD)},
      };

      const response = await fetch('/graphql/query', {
        method: 'POST',
        credentials: 'include',
        headers,
        body: body.toString(),
      });
      const text = await response.text();
      const normalizedText = text.replace(/^for \\(;;\\);?/, '').trim();
      let data = null;
      try {
        data = JSON.parse(normalizedText);
      } catch {}

      const rootField = ${JSON.stringify(INSTAGRAM_NOTE_ROOT_FIELD)};
      const note = data?.data?.[rootField]?.inbox_tray_item;
      const noteId = String(note?.inbox_tray_item_id || note?.id || '');
      if (response.ok && noteId) {
        return {
          ok: true,
          stage: 'publish',
          noteId,
          text: String(note?.note_dict?.text || input.content || ''),
        };
      }

      return {
        ok: false,
        stage: 'publish',
        status: response.status,
        text: normalizedText || text,
      };
    })()
  `;
}
cli({
    site: 'instagram',
    name: 'note',
    access: 'write',
    description: 'Publish a text Instagram note',
    domain: 'www.instagram.com',
    strategy: Strategy.UI,
    browser: true,
    args: [
        { name: 'content', positional: true, required: true, help: 'Note text (max 60 characters)' },
        { name: 'timeout', type: 'int', required: false, default: 120, help: 'Max seconds for the overall command (default: 120)' },
    ],
    columns: ['status', 'detail', 'noteId'],
    validateArgs: validateInstagramNoteArgs,
    func: async (page, kwargs) => {
        const browserPage = requirePage(page);
        const content = normalizeInstagramNoteContent(kwargs);
        await browserPage.goto(INSTAGRAM_INBOX_URL);
        await browserPage.wait({ time: 2 });
        const result = await browserPage.evaluate(buildPublishInstagramNoteJs(content));
        if (!result?.ok) {
            throw new CommandExecutionError(`Instagram note publish failed at ${String(result?.stage || 'unknown')}: ${String(result?.text || 'unknown error')}`);
        }
        return buildNoteSuccessResult(String(result.noteId || ''));
    },
});
