ALTER TABLE "sites" ADD COLUMN "gsc_authorized_user_id" text;--> statement-breakpoint
ALTER TABLE "sites" ADD CONSTRAINT "sites_gsc_authorized_user_id_user_id_fk" FOREIGN KEY ("gsc_authorized_user_id") REFERENCES "public"."user"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "sites_gsc_authorized_user_idx" ON "sites" USING btree ("gsc_authorized_user_id");--> statement-breakpoint
-- Backfill : rejoue la résolution owner-puis-admin de getOrgOwnerGscToken
-- (src/lib/gsc/owner.ts) pour ne casser aucune org qui fonctionne. Le regex
-- reproduit hasWebmastersScope : découpage sur virgules OU espaces, égalité de
-- jeton entière — pas un LIKE.
--
-- Une amélioration délibérée sur le code actuel, et une seule : celui-ci
-- n'inspecte QU'UN compte Google par candidat (ligne arbitraire, sans ORDER BY)
-- et abandonne le candidat si ce compte-là n'a pas le scope ; le JOIN ci-dessous
-- retient le candidat dès qu'AU MOINS UN de ses comptes Google porte le scope.
-- On ne réplique pas une sélection de ligne arbitraire. Seule conséquence
-- observable : un site dont l'owner a plusieurs comptes Google liés bascule sur
-- l'owner au lieu de l'admin — c'est le résultat attendu.
--
-- Borné aux lignes NULL : à l'application la colonne vient d'être créée et l'est
-- partout, mais si ce fichier est ré-exécuté à la main plus tard il ne doit pas
-- écraser (ni remettre à NULL) une autorité choisie depuis l'UI.
-- Les sites qui restent NULL sont ceux dont le worker échouait déjà.
UPDATE sites s SET gsc_authorized_user_id = (
  SELECT m.user_id FROM member m
  JOIN account a ON a.user_id = m.user_id AND a.provider_id = 'google'
  WHERE m.organization_id = s.org_id
    AND m.role IN ('owner','admin')
    AND a.scope ~ '(^|[[:space:],])https://www\.googleapis\.com/auth/webmasters\.readonly([[:space:],]|$)'
  ORDER BY CASE WHEN m.role = 'owner' THEN 0 ELSE 1 END, m.created_at, m.user_id
  LIMIT 1
) WHERE s.gsc_property IS NOT NULL AND s.gsc_authorized_user_id IS NULL;